{"record":{"id":"4430c4d863a60368","repo":"github/copilot-sdk","slug":"invalid-schema-json-for-parameter-param-name","errorCode":null,"errorMessage":"Invalid schema JSON for parameter ' + param.name() + ' in tool ' + toolName + ': + e.getMessage()","messagePattern":"Invalid schema JSON for parameter ' \\+ param\\.name\\(\\) \\+ ' in tool ' \\+ toolName \\+ ': \\+ e\\.getMessage\\(\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/rpc/ParamSchema.java","lineNumber":97,"sourceCode":"                throw new IllegalArgumentException(\n                        \"Duplicate parameter name '\" + param.name() + \"' in tool '\" + toolName + \"'\");\n            }\n        }\n\n        List<String> requiredNames = new ArrayList<>();\n        Map<String, Object> properties = new LinkedHashMap<>();\n\n        for (Param<?> param : params) {\n            Map<String, Object> typeSchema;\n            if (!param.schema().isEmpty()) {\n                try {\n                    @SuppressWarnings(\"unchecked\")\n                    Map<String, Object> parsed = mapper.readerFor(Map.class)\n                            .with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)\n                            .with(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS).readValue(param.schema());\n                    typeSchema = parsed;\n                } catch (Exception e) {\n                    throw new IllegalArgumentException(\"Invalid schema JSON for parameter '\" + param.name()\n                            + \"' in tool '\" + toolName + \"': \" + e.getMessage(), e);\n                }\n            } else {\n                typeSchema = forType(param.type());\n            }\n            Map<String, Object> enriched = new LinkedHashMap<>(typeSchema);\n            enriched.put(\"description\", param.description());\n            if (param.hasDefaultValue()) {\n                enriched.put(\"default\", ParamCoercion.coerceDefault(param, mapper));\n            }\n            properties.put(param.name(), Collections.unmodifiableMap(enriched));\n            if (param.required()) {\n                requiredNames.add(param.name());\n            }\n        }\n\n        return Map.of(\"type\", \"object\", \"properties\", Collections.unmodifiableMap(properties), \"required\",\n                Collections.unmodifiableList(requiredNames));","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/rpc/ParamSchema.java#L79-L115","documentation":"Thrown by ParamSchema.buildSchema when a Param supplies a custom schema() JSON string that cannot be parsed by Jackson (with FAIL_ON_TRAILING_TOKENS and USE_BIG_DECIMAL_FOR_FLOATS enabled). The message includes the parameter name, tool name, and Jackson's parse error, so invalid schema text is rejected at registration time instead of producing a broken tool schema.","triggerScenarios":"Passing schema() text that is not a single valid JSON object — malformed JSON, trailing garbage after the object, multiple JSON values concatenated, or an array/scalar instead of an object map.","commonSituations":"Hand-authored JSON Schema snippets with missing braces or trailing commas; embedding JSON in properties files where escaping is lost; concatenating two schema strings.","solutions":["Validate the schema string with a JSON linter/parse before registering the tool","Ensure schema() is exactly one JSON object (no trailing tokens, no leading BOM)","Generate the schema programmatically (forType / Map.of) instead of a hand-written string","Read e.getMessage() in the error — it pinpoints the exact offset and reason Jackson failed"],"exampleFix":"// before\nparam.schema = \"{\\\"type\\\":\\\"string\\\"} extra\"; // trailing token\n// after\nparam.schema = \"{\\\"type\\\":\\\"string\\\"}\";","handlingStrategy":"validation","validationCode":"new ObjectMapper().readerFor(Map.class).readValue(param.schema()); // pre-validate custom schema JSON","typeGuard":"boolean isValidJsonObject(String s) { try { new ObjectMapper().readValue(s, Map.class); return true; } catch (Exception e) { return false; } }","tryCatchPattern":"try { schema = ParamSchema.buildSchema(toolName, params); } catch (IllegalArgumentException e) { /* e.getMessage() contains the Jackson parse error and offset */ throw new ToolRegistrationException(toolName, e); }","preventionTips":["Lint hand-written JSON schema strings before committing them","Generate schema maps programmatically instead of string literals","Keep FAIL_ON_TRAILING_TOKENS semantics in mind: exactly one JSON object, no trailing text"],"tags":["java","rpc","json","tool-schema"],"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"}