{"record":{"id":"cbee5067514991ec","repo":"xpipe-io/xpipe","slug":"invalid-argument-for-key-key","errorCode":null,"errorMessage":"Invalid argument for key \" + key","messagePattern":"Invalid argument for key \" \\+ key","errorType":"exception","errorClass":"BeaconClientException","httpStatus":400,"severity":"error","filePath":"app/src/main/java/io/xpipe/app/beacon/mcp/McpToolHandler.java","lineNumber":94,"sourceCode":"            if (!(o instanceof String s) || s.isBlank()) {\n                return Optional.empty();\n            }\n\n            return Optional.of(s);\n        }\n\n        public String getStringArgument(String key) throws BeaconClientException {\n            if (request.arguments() == null) {\n                throw new BeaconClientException(\"Missing argument for key \" + key);\n            }\n\n            var o = request.arguments().get(key);\n            if (o == null) {\n                throw new BeaconClientException(\"Missing argument for key \" + key);\n            }\n\n            if (!(o instanceof String s) || s.isBlank()) {\n                throw new BeaconClientException(\"Invalid argument for key \" + key);\n            }\n\n            return s;\n        }\n\n        public Optional<Boolean> getOptionalBooleanArgument(String key) {\n            var o = request.arguments().get(key);\n            if (o == null) {\n                return Optional.empty();\n            }\n\n            if (!(o instanceof Boolean b)) {\n                return Optional.empty();\n            }\n\n            return Optional.of(b);\n        }\n","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/xpipe-io/xpipe/blob/d85ca821baa46092a320ebb13546d7240adb74f8/app/src/main/java/io/xpipe/app/beacon/mcp/McpToolHandler.java#L76-L112","documentation":"McpToolHandler.getStringArgument found the key but the value is either not a JSON string or is a blank string. Required string arguments must be non-blank strings, so the handler rejects any other type.","triggerScenarios":"Tool call arguments contain the key with a number, boolean, object, array, or \"\" (empty/whitespace) value where a non-blank string is required.","commonSituations":"LLM fills a string parameter with a number (e.g. port 22 instead of \"22\"); client sends null-like empty string; JSON unquoted value; coerced values from loosely typed clients.","solutions":["Send the argument as a non-empty JSON string","Convert numeric/boolean values to strings client-side before invoking","Use a dedicated typed getter (getBooleanArgument/getOptionalBooleanArgument) for non-string params","Validate types against the tool's inputSchema before the call"],"exampleFix":"// before\n{\"arguments\": {\"port\": 22}}\n// after\n{\"arguments\": {\"port\": \"22\"}}","handlingStrategy":"validation","validationCode":"Object o = toolCall.arguments().get(key);\nif (!(o instanceof String s) || s.isBlank()) {\n    throw new IllegalArgumentException(\"'\" + key + \"' must be a non-blank string\");\n}","typeGuard":"static boolean isNonBlankString(Object o) {\n    return o instanceof String s && !s.isBlank();\n}","tryCatchPattern":"try {\n    String v = handler.getStringArgument(key);\n} catch (BeaconClientException ex) {\n    if (ex.getMessage().contains(\"Invalid argument\")) {\n        // coerce (String.valueOf) or re-request the value\n    } else throw ex;\n}","preventionTips":["Quote string values in hand-built JSON payloads","Coerce numbers/booleans to strings client-side","Specify \"type\": \"string\" in the tool's inputSchema"],"tags":["mcp","arguments","type","xpipe"],"backgroundTag":"invalid-argument-value","analyzedSha":"d85ca821baa46092a320ebb13546d7240adb74f8","analyzedAt":"2026-09-06T14:30:08.251Z","contentChangedAt":"2026-09-06T14:30:08.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}