{"record":{"id":"5714527bdfa5a901","repo":"multica-ai/multica","slug":"s-must-be-a-json-object-or-null-to-clear","errorCode":null,"errorMessage":"%s must be a JSON object, or 'null' to clear","messagePattern":"(.+?) must be a JSON object, or 'null' to clear","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_agent.go","lineNumber":1347,"sourceCode":"\t\treturn nil, fmt.Errorf(\"%s: empty input; pass a JSON object\", flag)\n\t}\n\tvar probe any\n\tif err := json.Unmarshal([]byte(trimmed), &probe); err != nil {\n\t\tif allowNull {\n\t\t\treturn nil, fmt.Errorf(\"%s must be a valid JSON object, or 'null' to clear\", flag)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"%s must be a valid JSON object\", flag)\n\t}\n\tif probe == nil {\n\t\tif allowNull {\n\t\t\t// null → clear (NULL column server-side; on create it is a no-op).\n\t\t\treturn json.RawMessage(\"null\"), nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"%s must be a JSON object, not null\", flag)\n\t}\n\tif _, ok := probe.(map[string]any); !ok {\n\t\tif allowNull {\n\t\t\treturn nil, fmt.Errorf(\"%s must be a JSON object, or 'null' to clear\", flag)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"%s must be a JSON object\", flag)\n\t}\n\treturn json.RawMessage(trimmed), nil\n}\n\n// resolveMcpConfig collects the --mcp-config, --mcp-config-stdin, and\n// --mcp-config-file flags and returns the raw JSON value to send, a bool\n// indicating whether the caller supplied any of them, and any error. Mirrors\n// resolveCustomEnv; the only behavioural difference is the clear sentinel\n// (`null` here vs `{}` for custom_env), because mcp_config distinguishes an\n// explicit empty object from an absent config server-side.\nfunc resolveMcpConfig(cmd *cobra.Command) (json.RawMessage, bool, error) {\n\treturn resolveMcpJSONObject(cmd, \"mcp-config\", true)\n}\n\n// resolveMcpJSONObject collects the `<prefix>`, `<prefix>-stdin`, and\n// `<prefix>-file` flags. The three input channels are mutually exclusive so","sourceCodeStart":1329,"sourceCodeEnd":1365,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_agent.go#L1329-L1365","documentation":"Thrown by parseMcpJSONObject in the multica CLI when a JSON flag value (e.g. --mcp-config) parses successfully but is neither a JSON object nor null, while the flag allows the 'null' clear sentinel. The CLI only accepts a top-level object (or the literal null to clear the stored value); arrays, strings, numbers, and booleans are rejected before any API call. This is a client-side shape validation, so nothing reaches the server.","triggerScenarios":"Running e.g. `multica agent update <id> --mcp-config '[\"server1\"]'` or `--mcp-config '\"hello\"'` — any call to agent create/update/copy where resolveMcpConfig(cmd) (allowNull=true) receives valid JSON whose top-level value is not an object and not null.","commonSituations":"Users pasting a JSON array of server entries instead of an object keyed by server name; wrapping the config in quotes incorrectly so it parses as a string; feeding a config exported from a tool that emits an array.","solutions":["Wrap the value in a JSON object, e.g. --mcp-config '{\"servers\": [...]}' or an object keyed by server name","If the goal is to clear the stored mcp_config, pass the literal null: --mcp-config 'null'","Verify the payload shape first with: echo '<json>' | jq 'type' — it must print \"object\""],"exampleFix":"# before\nmultica agent update <id> --mcp-config '[\"fetch\", \"fs\"]'\n# after\nmultica agent update <id> --mcp-config '{\"fetch\": {\"command\": \"npx\", \"args\": [\"-y\", \"mcp-server-fetch\"]}}'","handlingStrategy":"validation","validationCode":"# before invoking the CLI, confirm top-level type is object (or null)\necho \"$CFG\" | jq -e 'type == \"object\" or (.) == null' >/dev/null || { echo \"bad mcp-config\"; exit 1; }\nmultica agent update <id> --mcp-config \"$CFG\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep MCP configs as objects keyed by server name, never arrays","Validate payloads with jq 'type' before passing them to the CLI","Store config files under version control and lint them in CI with jq -e 'type == \"object\"'"],"tags":["cli","json","validation","mcp","go"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}