{"record":{"id":"93a91af738fb07ec","repo":"github/copilot-sdk","slug":"unexpected-trailing-content-at-position-pos-r","errorCode":null,"errorMessage":"Unexpected trailing content at position <pos>: '<rest>'","messagePattern":"Unexpected trailing content at position <pos>: '<rest>'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java","lineNumber":946,"sourceCode":"            }\n        }\n        return sb.toString();\n    }\n\n    // ------------------------------------------------------------------\n    // JSON-to-Java source code conversion\n    // ------------------------------------------------------------------\n\n    /**\n     * Converts a JSON object string to a Java source expression. Supports nested\n     * objects, arrays, strings, numbers, booleans, and null.\n     */\n    static String jsonToMapOfSource(String json) {\n        JsonToSourceConverter converter = new JsonToSourceConverter(json);\n        String result = converter.parseObject();\n        converter.skipWhitespace();\n        if (converter.pos < json.length()) {\n            throw new IllegalArgumentException(\"Unexpected trailing content at position \" + converter.pos + \": '\"\n                    + json.substring(converter.pos) + \"'\");\n        }\n        return result;\n    }\n\n    /**\n     * Minimal recursive-descent JSON parser that produces helper calls and literal\n     * Java source expressions from a JSON string. Only used at compile time by the\n     * annotation processor.\n     */\n    private static final class JsonToSourceConverter {\n\n        private final String input;\n        private int pos;\n\n        JsonToSourceConverter(String input) {\n            this.input = input;\n            this.pos = 0;","sourceCodeStart":928,"sourceCodeEnd":964,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java#L928-L964","documentation":"jsonToMapOfSource parses a JSON object string with a hand-rolled JsonToSourceConverter and, after successfully parsing the top-level object, checks that the entire input has been consumed. Any non-whitespace characters left after the closing brace of the root object cause this IllegalArgumentException. The library is strict: the input must be exactly one JSON value with no extra text.","triggerScenarios":"Passing a string to jsonToMapOfSource that contains a valid JSON object followed by extra content, e.g. two concatenated JSON objects '{\"a\":1}{\"b\":2}', trailing text like '{\"a\":1} extra', or a JSON array when an object is expected (leading content the object parser rejects differently).","commonSituations":"Pasting/concatenating multiple JSON documents (NDJSON fed in whole); appending a semicolon or newline-plus-comment from copied code; logging frameworks wrapping the payload; tool output that includes a prefix/suffix around the JSON.","solutions":["Ensure the input is exactly one JSON object with nothing after the closing brace","If handling multiple JSON documents, split them (one per line for NDJSON) and call jsonToMapOfSource on each individually","Trim obvious junk, but note the parser already skips surrounding whitespace — look for real characters after the object","Validate the string with a standard JSON parser first to confirm it is a single well-formed value"],"exampleFix":"// before\nString json = line1 + line2; // two concatenated JSON objects\nString result = CopilotToolProcessor.jsonToMapOfSource(json);\n// after\nfor (String part : line.split(\"\\n\")) {\n    if (!part.isBlank()) {\n        String result = CopilotToolProcessor.jsonToMapOfSource(part);\n    }\n}","handlingStrategy":"validation","validationCode":"String trimmed = json.trim();\nif (!trimmed.startsWith(\"{\")) throw new IllegalArgumentException(\"Input must be a single JSON object\");\n// optionally: new JSONObject(trimmed) to validate it is one complete value","typeGuard":"static boolean isSingleJsonObject(String s) {\n    String t = s == null ? \"\" : s.trim();\n    return t.startsWith(\"{\") && t.endsWith(\"}\");\n}","tryCatchPattern":"try {\n    String result = CopilotToolProcessor.jsonToMapOfSource(json);\n} catch (IllegalArgumentException e) {\n    // log position + rest of input to identify trailing junk\n}","preventionTips":["Never concatenate JSON documents; parse them one at a time (NDJSON: split on newlines)","Feed the parser exactly one JSON value; strip logging wrappers before parsing","Round-trip validate with a standard JSON parser before calling custom parsers","Sanitize copied/pasted tool output for prefixes/suffixes"],"tags":["java","json","parsing","validation"],"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"}