crewAIInc/crewAI · error · SystemExit

Invalid --inputs JSON: expected an object.

Error message

Invalid --inputs JSON: expected an object.

What it means

Emitted by parse_inputs_json when --inputs parses as valid JSON but is not an object at the top level (e.g. a JSON array, string, number, or null). Crew inputs are a flat mapping of placeholder-name to value, so the parser enforces isinstance(parsed, dict) and exits 1 with this message otherwise.

Source

Thrown at lib/cli/src/crewai_cli/input_prompt.py:37

import click

from crewai_cli.utils import enable_prompt_line_editing, is_dmn_mode_enabled


def parse_inputs_json(inputs: str | None) -> dict[str, Any] | None:
    """Parse a ``--inputs`` JSON object, exiting with a pointed error if invalid."""
    if inputs is None:
        return None

    try:
        parsed = json.loads(inputs)
    except json.JSONDecodeError as exc:
        click.echo(f"Invalid --inputs JSON: {exc}", err=True)
        raise SystemExit(1) from exc

    if not isinstance(parsed, dict):
        click.echo("Invalid --inputs JSON: expected an object.", err=True)
        raise SystemExit(1)

    return parsed


def closest_name(key: str, candidates: Iterable[str]) -> str | None:
    """Nearest candidate name to a likely typo, if one is close enough."""
    matches = difflib.get_close_matches(key, list(candidates), n=1, cutoff=0.7)
    return matches[0] if matches else None


def is_interactive() -> bool:
    """Prompt only in an interactive terminal, never in non-interactive mode."""
    return not is_dmn_mode_enabled() and sys.stdin.isatty()


def prompt_for_inputs(
    names: list[str],
    *,

View on GitHub (pinned to 754d7323be)

Solutions

  1. Wrap values in an object with named keys: `--inputs '{"topic": "AI"}'`
  2. Check for stray brackets/quotes around the whole argument
  3. If building the string in code, ensure you serialize a dict, not a list/scalar

Example fix

# before
crewai run --inputs '["topic", "AI"]'
# after
crewai run --inputs '{"topic": "AI"}'
Defensive patterns

Strategy: type-guard

Validate before calling

import json

def inputs_is_object(s: str | None) -> bool:
    if s is None:
        return True
    try:
        return isinstance(json.loads(s), dict)
    except json.JSONDecodeError:
        return False

Type guard

def is_json_object(s: str) -> bool:
    import json
    try:
        return isinstance(json.loads(s), dict)
    except json.JSONDecodeError:
        return False

Prevention

When it happens

Trigger: Passing `--inputs '["topic"]'`, `--inputs '"AI"'`, or `--inputs 'null'` — syntactically valid JSON whose root is not an object. Commonly happens when users wrap the object in brackets or pass a raw string value instead of a key/value mapping.

Common situations: Misreading the option as taking a list of values; passing a JSON file's inner array instead of the wrapper object; constructing the argument programmatically and serializing the wrong variable (a list instead of dict).

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/a61eb1e2c950f8e3. Report an issue: GitHub.