github/copilot-sdk · error · IllegalArgumentException
Expected ' ' at position but got '<char|EOF>
Error message
Expected '<c>' at position <pos> but got '<char|EOF>'
What it means
The expect(c) helper in CopilotToolProcessor's JSON parser asserts that the current character equals the expected structural character (e.g. ':', ',', '}', ']') and advances; otherwise it throws IllegalArgumentException reporting the expected character, position, and what was actually found (or EOF). This is the generic structural-mismatch error of the hand-rolled parser.
Solutions
- Use the message's position/actual-character info to fix the delimiter at that spot.
- Validate the JSON with a standard parser before passing it to the tool.
- Catch IllegalArgumentException around the parse and fall back to a lenient JSON repair library.
Example fix
// before
{"name": "x" "age": 1}
// after
{"name": "x", "age": 1} Defensive patterns
Strategy: try-catch
Validate before calling
static void assertWellFormed(String json) {
try { new com.fasterxml.jackson.databind.ObjectMapper().readTree(json); }
catch (java.io.IOException e) { throw new IllegalArgumentException("not valid JSON", e); }
} Type guard
static boolean looksLikeJsonObject(String s) {
String t = s == null ? "" : s.trim();
return t.startsWith("{") && t.endsWith("}");
} Try / catch
try {
processor.parse(args);
} catch (IllegalArgumentException e) {
// message contains: expected char, position, actual char — surface both to the caller
return Result.syntaxError(parsePosFrom(e.getMessage()), e.getMessage());
} Prevention
- Always double-quote keys and string values; never use single quotes.
- Check delimiters (,:}) when hand-editing JSON tool arguments.
- Pre-generate arguments with a JSON serializer instead of templates.
When it happens
Trigger: Malformed JSON such as missing colons ({"a" 1}), missing commas between members, wrong closing bracket ([1}), or trailing text where the delimiter was expected.
Common situations: LLM tool-call arguments with dropped punctuation, hand-edited JSON, single quotes used instead of double quotes, unquoted keys or trailing commas in unexpected spots.
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
- Expected number at position
- Unexpected trailing content at position
- Unescaped control character at position <pos-1>
- Unterminated string escape at position
- Invalid escape sequence \
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/83b95b5b694926c0.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java:1177
while (pos < input.length() && isJsonWhitespace(input.charAt(pos))) {
pos++;
}
}
private boolean isJsonWhitespace(char c) {
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
private char peek() {
if (pos >= input.length()) {
throw new IllegalArgumentException("Unexpected end of JSON");
}
return input.charAt(pos);
}
private void expect(char c) {
if (pos >= input.length() || input.charAt(pos) != c) {
throw new IllegalArgumentException("Expected '" + c + "' at position " + pos + " but got '"
+ (pos < input.length() ? input.charAt(pos) : "EOF") + "'");
}
pos++;
}
private boolean tryConsume(char c) {
if (pos < input.length() && input.charAt(pos) == c) {
pos++;
return true;
}
return false;
}
}
private static String escapeJava(String s) {
if (s == null) {
return "";
}View on GitHub (pinned to cd8cf15dc3)