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

  1. Ensure every \u escape has exactly four hex digits: '\u00e9' not '\u0' or '\u00'
  2. Check whether the input was truncated upstream and re-obtain the full payload
  3. Use a JSON serializer to encode non-ASCII characters correctly (it will emit complete escapes or raw UTF-8)
  4. 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

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


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)