multica-ai/multica · error

%s must be a JSON object, or 'null' to clear

Error message

%s must be a JSON object, or 'null' to clear

What it means

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.

Source

Thrown at server/cmd/multica/cmd_agent.go:1347

		return nil, fmt.Errorf("%s: empty input; pass a JSON object", flag)
	}
	var probe any
	if err := json.Unmarshal([]byte(trimmed), &probe); err != nil {
		if allowNull {
			return nil, fmt.Errorf("%s must be a valid JSON object, or 'null' to clear", flag)
		}
		return nil, fmt.Errorf("%s must be a valid JSON object", flag)
	}
	if probe == nil {
		if allowNull {
			// null → clear (NULL column server-side; on create it is a no-op).
			return json.RawMessage("null"), nil
		}
		return nil, fmt.Errorf("%s must be a JSON object, not null", flag)
	}
	if _, ok := probe.(map[string]any); !ok {
		if allowNull {
			return nil, fmt.Errorf("%s must be a JSON object, or 'null' to clear", flag)
		}
		return nil, fmt.Errorf("%s must be a JSON object", flag)
	}
	return json.RawMessage(trimmed), nil
}

// resolveMcpConfig collects the --mcp-config, --mcp-config-stdin, and
// --mcp-config-file flags and returns the raw JSON value to send, a bool
// indicating whether the caller supplied any of them, and any error. Mirrors
// resolveCustomEnv; the only behavioural difference is the clear sentinel
// (`null` here vs `{}` for custom_env), because mcp_config distinguishes an
// explicit empty object from an absent config server-side.
func resolveMcpConfig(cmd *cobra.Command) (json.RawMessage, bool, error) {
	return resolveMcpJSONObject(cmd, "mcp-config", true)
}

// resolveMcpJSONObject collects the `<prefix>`, `<prefix>-stdin`, and
// `<prefix>-file` flags. The three input channels are mutually exclusive so

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Wrap the value in a JSON object, e.g. --mcp-config '{"servers": [...]}' or an object keyed by server name
  2. If the goal is to clear the stored mcp_config, pass the literal null: --mcp-config 'null'
  3. Verify the payload shape first with: echo '<json>' | jq 'type' — it must print "object"

Example fix

# before
multica agent update <id> --mcp-config '["fetch", "fs"]'
# after
multica agent update <id> --mcp-config '{"fetch": {"command": "npx", "args": ["-y", "mcp-server-fetch"]}}'
Defensive patterns

Strategy: validation

Validate before calling

# before invoking the CLI, confirm top-level type is object (or null)
echo "$CFG" | jq -e 'type == "object" or (.) == null' >/dev/null || { echo "bad mcp-config"; exit 1; }
multica agent update <id> --mcp-config "$CFG"

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/5714527bdfa5a901. Report an issue: GitHub.