github/copilot-sdk · error · IllegalArgumentException
Incomplete Unicode escape at position <pos-2>
Error message
Incomplete Unicode escape at position <pos-2>
What it means
When parseEscape sees \u it delegates to parseUnicodeEscape, which requires exactly four more characters (four hex digits) after the \u prefix. If fewer than four characters remain in the input, the Unicode escape is incomplete and this IllegalArgumentException is thrown at the position of the backslash (pos-2).
Solutions
- Ensure every \u escape has exactly four hex digits: '\u00e9' not '\u0' or '\u00'
- Check whether the input was truncated upstream and re-obtain the full payload
- Use a JSON serializer to encode non-ASCII characters correctly (it will emit complete escapes or raw UTF-8)
- Validate the JSON with a standard parser to pinpoint all malformed escapes before retrying
Example fix
// before
String json = "{\"ch\":\"\\u00\"}"; // incomplete escape
// after
String json = "{\"ch\":\"\\u00e9\"}"; // 4 hex digits Defensive patterns
Strategy: try-catch
Validate before calling
java.util.regex.Matcher m = java.util.regex.Pattern.compile("\\\\\\\\u(?!\\\\p{XDigit}{4})").matcher(json);
if (m.find()) {
throw new IllegalArgumentException("Incomplete \\u escape at index " + m.start());
} Try / catch
try {
String result = CopilotToolProcessor.jsonToMapOfSource(json);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Incomplete Unicode escape")) {
// input truncated or hand-written escape missing hex digits; refetch/fix
}
} Prevention
- Always write four hex digits after \u
- Guard against truncation: check payload ends with the expected terminator (e.g. '}')
- Template engines: ensure \uXXXX placeholders are fully substituted
- Prefer serializers that emit valid escapes or raw UTF-8
When it happens
Trigger: A JSON string ending with a truncated Unicode escape, e.g. '"caf\u00' or '\u0' at end of input, typically from truncation or hand-written escapes with too few digits.
Common situations: Hand-typed \u escapes missing digits; payloads truncated by a fixed-size log buffer or network read; copy/paste dropping trailing characters.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Invalid Unicode escape at position <pos-1>
- Unterminated string escape at position
- Invalid escape sequence \
- Unexpected trailing content at position
- Unescaped control character at position <pos-1>
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/e42cf721dc588a06.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1062
throw new IllegalArgumentException("Unterminated string escape at position " + pos);
}
char escaped = input.charAt(pos++);
return switch (escaped) {
case '"', '\\', '/' -> escaped;
case 'b' -> '\b';
case 'f' -> '\f';
case 'n' -> '\n';
case 'r' -> '\r';
case 't' -> '\t';
case 'u' -> parseUnicodeEscape();
default -> throw new IllegalArgumentException(
"Invalid escape sequence \\" + escaped + " at position " + (pos - 2));
};
}
private char parseUnicodeEscape() {
if (pos + 4 > input.length()) {
throw new IllegalArgumentException("Incomplete Unicode escape at position " + (pos - 2));
}
int value = 0;
for (int i = 0; i < 4; i++) {
char hex = input.charAt(pos++);
if (!isAsciiHexDigit(hex)) {
throw new IllegalArgumentException("Invalid Unicode escape at position " + (pos - 1));
}
int digit = Character.digit(hex, 16);
value = (value << 4) | digit;
}
return (char) value;
}
private boolean isAsciiHexDigit(char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
private String parseBoolean() {View on GitHub (pinned to cd8cf15dc3)