iOfficeAI/OfficeCLI · error · ArgumentException
{propName} contains an unpaired low surrogate U+{(int)c:X4}
Error message
{propName} contains an unpaired low surrogate U+{(int)c:X4} at position {i}. Use a complete UTF-16 surrogate pair. What it means
Thrown by ValidateXmlText when a low surrogate (U+DC00–U+DFFF) appears without a preceding high surrogate. Low surrogates are only valid as the second half of a pair; a lone low surrogate is illegal in XML 1.0 character data.
Source
Thrown at src/officecli/Core/ParseHelpers.cs:866
// strict default so '\v' can never reach raw character data.
if (c == '\v' && allowSoftBreakChar) continue;
if (c < 0x20)
throw new ArgumentException(
$"{propName} contains XML-illegal control character U+{(int)c:X4} at position {i}. " +
"Allowed control chars: \\t, \\n, \\r" +
(allowSoftBreakChar ? ", \\v." : "."));
// UTF-16 surrogates only valid in pairs (high then low). A lone
// half is illegal in XML 1.0 character data.
if (char.IsHighSurrogate(c))
{
if (i + 1 >= value.Length || !char.IsLowSurrogate(value[i + 1]))
throw new ArgumentException(
$"{propName} contains an unpaired high surrogate U+{(int)c:X4} at position {i}. Use a complete UTF-16 surrogate pair.");
i++; // skip the matched low surrogate
continue;
}
if (char.IsLowSurrogate(c))
throw new ArgumentException(
$"{propName} contains an unpaired low surrogate U+{(int)c:X4} at position {i}. Use a complete UTF-16 surrogate pair.");
if (c == 0xFFFE || c == 0xFFFF)
throw new ArgumentException(
$"{propName} contains the XML-illegal noncharacter U+{(int)c:X4} at position {i}.");
}
}
}
View on GitHub (pinned to 1ced45e900)
Solutions
- Reconstruct or re-encode the original text so every low surrogate is preceded by its matching high surrogate.
- Use text-element-aware APIs (StringInfo) for substring/remove operations on text that may contain supplementary-plane characters.
- Filter out lone surrogates before setting the value if you cannot recover the pair.
Example fix
// before var s = "\uDE00"; // lone low surrogate // after var s = "\uD83D\uDE00"; // complete pair
Defensive patterns
Strategy: validation
Validate before calling
static bool HasNoLoneSurrogates(string s)
{
for (int i = 0; i < s.Length; i++)
{
if (char.IsHighSurrogate(s, i) && (i + 1 >= s.Length || !char.IsLowSurrogate(s[i + 1]))) return false;
if (char.IsLowSurrogate(s, i) && (i == 0 || !char.IsHighSurrogate(s[i - 1]))) return false;
}
return true;
} Prevention
- Keep surrogate pairs intact during text manipulation.
- Use text-element-aware APIs for remove/substring.
- Strip lone surrogates from untrusted input before setting.
When it happens
Trigger: A string that starts with or contains an isolated low surrogate, e.g. from slicing a pair and keeping the trailing half, or from manually constructing chars from raw code units where the high half was dropped.
Common situations: String slicing/removal that deleted the high half of an emoji but kept the low half; decoding errors; constructing strings from unvalidated char arrays.
Related errors
- {propName} contains an unpaired high surrogate U+{(int)c:X4}
- {propName} contains the XML-illegal noncharacter U+{(int)c:X
- {propName} contains XML-illegal control character U+{(int)c:
- Invalid '{propertyName}' value '{value}': degrees must be in
- Invalid color value: '{value}'. Expected 6-digit hex RGB (e.
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/7c9cd712c96a2cee.
Report an issue: GitHub.