charmbracelet/crush · error
%s: --%s expects a JSON object, got %q
Error message
%s: --%s expects a JSON object, got %q
What it means
This error is thrown by parseFlagValue when a flag declared with kind flagJSONObject receives a value that is not valid JSON or does not unmarshal into a JSON object (map[string]any). The check `err != nil || object == nil` also rejects bare `null` and, because the target type is a map, any array, string, number, or boolean. It exists so flags like --provider-options only accept object-shaped JSON that can be merged into a child map.
Source
Thrown at internal/shellconfig/flags.go:162
if err != nil {
return nil, 0, fmt.Errorf("%s: --%s expects a number, got %q", args[0], name, v)
}
return f, i + 2, nil
case flagKeyValue:
if i+2 >= len(args) {
return nil, 0, fmt.Errorf("%s: --%s requires a key and value", args[0], name)
}
return [2]string{args[i+1], args[i+2]}, i + 3, nil
case flagJSONObject:
v, err := nextArg(args, i, name)
if err != nil {
return nil, 0, err
}
var object map[string]any
if err := json.Unmarshal([]byte(v), &object); err != nil || object == nil {
return nil, 0, fmt.Errorf("%s: --%s expects a JSON object, got %q", args[0], name, v)
}
return object, i + 2, nil
case flagJSONAny:
v, err := nextArg(args, i, name)
if err != nil {
return nil, 0, err
}
var parsed any
if err := json.Unmarshal([]byte(v), &parsed); err != nil {
return nil, 0, fmt.Errorf("%s: --%s expects valid JSON, got %q: %s", args[0], name, v, err)
}
return parsed, i + 2, nil
default:
return nil, 0, fmt.Errorf("%s: --%s has unknown flag kind", args[0], name)
}
}View on GitHub (pinned to 7944b8e522)
Solutions
- Validate the value parses as a JSON object first: `echo '<value>' | jq -e 'type == "object"'`.
- Quote the entire JSON blob in single quotes so the shell does not strip braces or double quotes.
- Use double quotes for all JSON keys and string values, no trailing commas: `'{"temperature": 0.5}'`.
- If passing non-object JSON, use the appropriate flag that accepts arbitrary JSON instead of the object-typed flag.
Example fix
// before
provider add x --provider-options '{temperature: 0.5,}'
// after
provider add x --provider-options '{"temperature": 0.5}' Defensive patterns
Strategy: validation
Validate before calling
echo "$value" | jq -e 'type == "object"' >/dev/null || { echo "flag value must be a JSON object" >&2; exit 2; } Type guard
func isJSONObject(s string) bool {
var m map[string]any
return json.Unmarshal([]byte(s), &m) == nil && m != nil
} Try / catch
if err := applyFlags(specs, args, start, target, cmd, stderr); err != nil {
if strings.Contains(err.Error(), "expects a JSON object") {
fmt.Fprintln(stderr, "Value must be a JSON object like '{\"key\": 1}', not an array or scalar")
}
return err
} Prevention
- Validate with jq (type == "object") before passing the value.
- Single-quote the entire JSON blob so the shell preserves braces and double quotes.
- Remember null is rejected too — a JSON object must have at least {} shape.
- Prefer repeated simple flags over hand-written JSON when available.
When it happens
Trigger: Calling a builtin flag like --provider-options with a value that is invalid JSON (e.g. `{api_key: x}` with unquoted keys, single quotes, trailing commas), a JSON array (`[1,2]`), a bare scalar (`"foo"`, `42`, `true`), or the literal `null`.
Common situations: Hand-writing provider options with unquoted keys or Python-style True/False; shell stripping double quotes (typing --provider-options '{"a":1}' without proper quoting so the shell eats braces/quotes); passing a JSON array where an object is expected; copying JSON with trailing commas.
Related errors
- %s: --%s expects valid JSON, got %q: %s
- %s: --%s requires a key and value
- %s: --%s requires a value
- failed to load projects: %w
- ${sessionList} Use more characters or the full hash
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/ed33e2fea50d2434.
Report an issue: GitHub.