diff --git a/common/plotters/PS_plotter.cpp b/common/plotters/PS_plotter.cpp
index 32fb018347..6e83f55d91 100644
--- a/common/plotters/PS_plotter.cpp
+++ b/common/plotters/PS_plotter.cpp
@@ -290,10 +290,6 @@ std::string PSLIKE_PLOTTER::encodeStringForPlotter( const wxString& aUnicode )
         {
             switch (ch)
             {
-            // The ~ shouldn't reach the outside
-            case '~':
-                break;
-
             // These characters must be escaped
             case '(':
             case ')':
@@ -324,7 +320,7 @@ int PSLIKE_PLOTTER::returnPostscriptTextWidth( const wxString& aText, int aXSize
     for( wchar_t asciiCode : aText)
     {
         // Skip the negation marks and untabled points.
-        if( asciiCode != '~' && asciiCode < 256 )
+        if( asciiCode < 256 )
             tally += width_table[asciiCode];
     }
 
diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp
index 71fd867d19..0f64ff1062 100644
--- a/eeschema/sch_field.cpp
+++ b/eeschema/sch_field.cpp
@@ -253,9 +253,6 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT
     if( IsNameShown() && aAllowExtraText )
         text = GetShownName() << wxS( ": " ) << text;
 
-    if( text == wxS( "~" ) ) // Legacy placeholder for empty string
-        text = wxS( "" );
-
     // The iteration here it to allow for nested variables in the
     // text strings (e.g. ${${VAR}}).  Although the symbols and sheets
     // and labels recurse, text that is none of those types such as text
diff --git a/eeschema/sch_file_versions.h b/eeschema/sch_file_versions.h
index 29d02039e8..bb66e82e4d 100644
--- a/eeschema/sch_file_versions.h
+++ b/eeschema/sch_file_versions.h
@@ -52,7 +52,9 @@
 //#define SEXPR_SYMBOL_LIB_FILE_VERSION  20231120  // generator_version; V8 cleanups
 //#define SEXPR_SYMBOL_LIB_FILE_VERSION  20240529  // Embedded Files
 //#define SEXPR_SYMBOL_LIB_FILE_VERSION  20240819  // Embedded Files - Update hash algorithm to Murmur3
-#define   SEXPR_SYMBOL_LIB_FILE_VERSION  20241209  // Private flags for SCH_FIELDs
+//#define SEXPR_SYMBOL_LIB_FILE_VERSION  20241209  // Private flags for SCH_FIELDs
+#define   SEXPR_SYMBOL_LIB_FILE_VERSION  20250318  // ~ no longer means empty text
+
 /**
  * Schematic file version.
  */
@@ -116,4 +118,5 @@
 //#define SEXPR_SCHEMATIC_FILE_VERSION 20241209  // Private flags for SCH_FIELDs
 //#define SEXPR_SCHEMATIC_FILE_VERSION 20250114  // Full paths for text variable cross references
 //#define SEXPR_SCHEMATIC_FILE_VERSION 20250222  // Hatched fills for shapes
-#define   SEXPR_SCHEMATIC_FILE_VERSION 20250227  // Support for local power symbols
+//#define SEXPR_SCHEMATIC_FILE_VERSION 20250227  // Support for local power symbols
+#define   SEXPR_SCHEMATIC_FILE_VERSION 20250318  // ~ no longer means empty text
diff --git a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp
index 9fdccdd540..9e6ff3dfe0 100644
--- a/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp
+++ b/eeschema/sch_io/kicad_sexpr/sch_io_kicad_sexpr_parser.cpp
@@ -1012,7 +1012,11 @@ SCH_FIELD* SCH_IO_KICAD_SEXPR_PARSER::parseProperty( std::unique_ptr<LIB_SYMBOL>
     }
 
     // Empty property values are valid.
-    value = FromUTF8();
+
+    if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+        value = wxEmptyString;
+    else
+        value = FromUTF8();
 
     field->SetText( value );
 
@@ -1610,6 +1614,8 @@ SCH_PIN* SCH_IO_KICAD_SEXPR_PARSER::parseSymbolPin()
 
             if( m_requiredVersion < 20210606 )
                 pin->SetName( ConvertToNewOverbarNotation( FromUTF8() ) );
+            else if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                pin->SetName( wxEmptyString );
             else
                 pin->SetName( FromUTF8() );
 
@@ -1646,7 +1652,13 @@ SCH_PIN* SCH_IO_KICAD_SEXPR_PARSER::parseSymbolPin()
                                    CurLineNumber(), CurOffset() );
             }
 
-            pin->SetNumber( FromUTF8() );
+            if( m_requiredVersion < 20210606 )
+                pin->SetNumber( ConvertToNewOverbarNotation( FromUTF8() ) );
+            else if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                pin->SetNumber( wxEmptyString );
+            else
+                pin->SetNumber( FromUTF8() );
+
             token = NextTok();
 
             if( token != T_RIGHT )
@@ -2211,7 +2223,12 @@ SCH_FIELD* SCH_IO_KICAD_SEXPR_PARSER::parseSchField( SCH_ITEM* aParent )
     }
 
     // Empty property values are valid.
-    wxString value = FromUTF8();
+    wxString value;
+
+    if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+        value = wxEmptyString;
+    else
+        value = FromUTF8();
 
     FIELD_T fieldId = FIELD_T::USER;
 
@@ -2555,13 +2572,23 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseSchSymbolInstances( SCH_SCREEN* aScreen )
 
                 case T_value:
                     NeedSYMBOL();
-                    instance.m_Value = FromUTF8();
+
+                    if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                        instance.m_Value = wxEmptyString;
+                    else
+                        instance.m_Value = FromUTF8();
+
                     NeedRIGHT();
                     break;
 
                 case T_footprint:
                     NeedSYMBOL();
-                    instance.m_Footprint = FromUTF8();
+
+                    if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                        instance.m_Footprint = wxEmptyString;
+                    else
+                        instance.m_Footprint = FromUTF8();
+
                     NeedRIGHT();
                     break;
 
@@ -3134,13 +3161,23 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
 
                 case T_value:
                     NeedSYMBOL();
-                    symbol->SetValueFieldText( FromUTF8() );
+
+                    if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                        symbol->SetValueFieldText( wxEmptyString );
+                    else
+                        symbol->SetValueFieldText( FromUTF8() );
+
                     NeedRIGHT();
                     break;
 
                 case T_footprint:
                     NeedSYMBOL();
-                    symbol->SetFootprintFieldText( FromUTF8() );
+
+                    if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                        symbol->SetFootprintFieldText( wxEmptyString );
+                    else
+                        symbol->SetFootprintFieldText( FromUTF8() );
+
                     NeedRIGHT();
                     break;
 
@@ -3207,13 +3244,23 @@ SCH_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseSchematicSymbol()
 
                         case T_value:
                             NeedSYMBOL();
-                            symbol->SetValueFieldText( FromUTF8() );
+
+                            if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                                symbol->SetValueFieldText( wxEmptyString );
+                            else
+                                symbol->SetValueFieldText( FromUTF8() );
+
                             NeedRIGHT();
                             break;
 
                         case T_footprint:
                             NeedSYMBOL();
-                            symbol->SetFootprintFieldText( FromUTF8() );
+
+                            if( m_requiredVersion < 20250318 && FromUTF8() == "~" )
+                                symbol->SetFootprintFieldText( wxEmptyString );
+                            else
+                                symbol->SetFootprintFieldText( FromUTF8() );
+
                             NeedRIGHT();
                             break;
 
diff --git a/eeschema/sch_label.cpp b/eeschema/sch_label.cpp
index 88b284f134..8ef2e55d81 100644
--- a/eeschema/sch_label.cpp
+++ b/eeschema/sch_label.cpp
@@ -833,11 +833,7 @@ wxString SCH_LABEL_BASE::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowE
 
     wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth );
 
-    if( text == wxS( "~" ) ) // Legacy placeholder for empty string
-    {
-        text = wxS( "" );
-    }
-    else if( HasTextVars() )
+    if( HasTextVars() )
     {
         if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth )
             text = ExpandTextVars( text, &textResolver );
diff --git a/eeschema/sch_pin.cpp b/eeschema/sch_pin.cpp
index 87de8f0bc7..81d26842c3 100644
--- a/eeschema/sch_pin.cpp
+++ b/eeschema/sch_pin.cpp
@@ -532,19 +532,13 @@ wxString SCH_PIN::GetShownName() const
     else if( m_libPin )
         return m_libPin->GetShownName();
 
-    if( m_name == wxS( "~" ) )
-        return wxEmptyString;
-    else
-        return m_name;
+    return m_name;
 }
 
 
 wxString SCH_PIN::GetShownNumber() const
 {
-    if( m_number == wxS( "~" ) )
-        return wxEmptyString;
-    else
-        return m_number;
+    return m_number;
 }
 
 
diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp
index 86d5407914..94e0eb37d6 100644
--- a/eeschema/sch_text.cpp
+++ b/eeschema/sch_text.cpp
@@ -352,11 +352,7 @@ wxString SCH_TEXT::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraTe
 
     wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth );
 
-    if( text == wxS( "~" ) ) // Legacy placeholder for empty string
-    {
-        text = wxS( "" );
-    }
-    else if( HasTextVars() )
+    if( HasTextVars() )
     {
         if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth )
             text = ExpandTextVars( text, &textResolver );
diff --git a/eeschema/symbol_checker.cpp b/eeschema/symbol_checker.cpp
index c1ac9de1a6..1b05da9bb2 100644
--- a/eeschema/symbol_checker.cpp
+++ b/eeschema/symbol_checker.cpp
@@ -65,10 +65,10 @@ void CheckDuplicatePins( LIB_SYMBOL* aSymbol, std::vector<wxString>& aMessages,
         wxString pinName;
         wxString nextName;
 
-        if( pin->GetName() != "~"  && !pin->GetName().IsEmpty() )
+        if( !pin->GetName().IsEmpty() )
             pinName = " '" + pin->GetName() + "'";
 
-        if( next->GetName() != "~"  && !next->GetName().IsEmpty() )
+        if( !next->GetName().IsEmpty() )
             nextName = " '" + next->GetName() + "'";
 
         if( aSymbol->HasAlternateBodyStyle() && next->GetBodyStyle() )
diff --git a/include/dsnlexer.h b/include/dsnlexer.h
index 01fa01c030..5572c42873 100644
--- a/include/dsnlexer.h
+++ b/include/dsnlexer.h
@@ -423,6 +423,9 @@ public:
      */
     wxString FromUTF8() const
     {
+if( wxString::FromUTF8( curText.c_str() ).IsSameAs( "~" ) )
+wxASSERT( true );
+
         return wxString::FromUTF8( curText.c_str() );
     }