{"record":{"id":"83b95b5b694926c0","repo":"github/copilot-sdk","slug":"expected-c-at-position-pos-but-got-char-eo","errorCode":null,"errorMessage":"Expected '<c>' at position <pos> but got '<char|EOF>'","messagePattern":"Expected '<c>' at position <pos> but got '<char\\|EOF>'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java","lineNumber":1177,"sourceCode":"            while (pos < input.length() && isJsonWhitespace(input.charAt(pos))) {\n                pos++;\n            }\n        }\n\n        private boolean isJsonWhitespace(char c) {\n            return c == ' ' || c == '\\t' || c == '\\r' || c == '\\n';\n        }\n\n        private char peek() {\n            if (pos >= input.length()) {\n                throw new IllegalArgumentException(\"Unexpected end of JSON\");\n            }\n            return input.charAt(pos);\n        }\n\n        private void expect(char c) {\n            if (pos >= input.length() || input.charAt(pos) != c) {\n                throw new IllegalArgumentException(\"Expected '\" + c + \"' at position \" + pos + \" but got '\"\n                        + (pos < input.length() ? input.charAt(pos) : \"EOF\") + \"'\");\n            }\n            pos++;\n        }\n\n        private boolean tryConsume(char c) {\n            if (pos < input.length() && input.charAt(pos) == c) {\n                pos++;\n                return true;\n            }\n            return false;\n        }\n    }\n\n    private static String escapeJava(String s) {\n        if (s == null) {\n            return \"\";\n        }","sourceCodeStart":1159,"sourceCodeEnd":1195,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java#L1159-L1195","documentation":"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.","triggerScenarios":"Malformed JSON such as missing colons ({\"a\" 1}), missing commas between members, wrong closing bracket ([1}), or trailing text where the delimiter was expected.","commonSituations":"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.","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."],"exampleFix":"// before\n{\"name\": \"x\" \"age\": 1}\n// after\n{\"name\": \"x\", \"age\": 1}","handlingStrategy":"try-catch","validationCode":"static void assertWellFormed(String json) {\n    try { new com.fasterxml.jackson.databind.ObjectMapper().readTree(json); }\n    catch (java.io.IOException e) { throw new IllegalArgumentException(\"not valid JSON\", e); }\n}","typeGuard":"static boolean looksLikeJsonObject(String s) {\n    String t = s == null ? \"\" : s.trim();\n    return t.startsWith(\"{\") && t.endsWith(\"}\");\n}","tryCatchPattern":"try {\n    processor.parse(args);\n} catch (IllegalArgumentException e) {\n    // message contains: expected char, position, actual char — surface both to the caller\n    return Result.syntaxError(parsePosFrom(e.getMessage()), e.getMessage());\n}","preventionTips":["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."],"tags":["json","parsing","syntax","tool-arguments"],"backgroundTag":"json-parse-error","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}