{"record":{"id":"a61eb1e2c950f8e3","repo":"crewAIInc/crewAI","slug":"invalid-inputs-json-expected-an-object","errorCode":null,"errorMessage":"Invalid --inputs JSON: expected an object.","messagePattern":"Invalid --inputs JSON: expected an object\\.","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"lib/cli/src/crewai_cli/input_prompt.py","lineNumber":37,"sourceCode":"import click\n\nfrom crewai_cli.utils import enable_prompt_line_editing, is_dmn_mode_enabled\n\n\ndef parse_inputs_json(inputs: str | None) -> dict[str, Any] | None:\n    \"\"\"Parse a ``--inputs`` JSON object, exiting with a pointed error if invalid.\"\"\"\n    if inputs is None:\n        return None\n\n    try:\n        parsed = json.loads(inputs)\n    except json.JSONDecodeError as exc:\n        click.echo(f\"Invalid --inputs JSON: {exc}\", err=True)\n        raise SystemExit(1) from exc\n\n    if not isinstance(parsed, dict):\n        click.echo(\"Invalid --inputs JSON: expected an object.\", err=True)\n        raise SystemExit(1)\n\n    return parsed\n\n\ndef closest_name(key: str, candidates: Iterable[str]) -> str | None:\n    \"\"\"Nearest candidate name to a likely typo, if one is close enough.\"\"\"\n    matches = difflib.get_close_matches(key, list(candidates), n=1, cutoff=0.7)\n    return matches[0] if matches else None\n\n\ndef is_interactive() -> bool:\n    \"\"\"Prompt only in an interactive terminal, never in non-interactive mode.\"\"\"\n    return not is_dmn_mode_enabled() and sys.stdin.isatty()\n\n\ndef prompt_for_inputs(\n    names: list[str],\n    *,","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/cli/src/crewai_cli/input_prompt.py#L19-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Wrap values in an object with named keys: `--inputs '{\"topic\": \"AI\"}'`","Check for stray brackets/quotes around the whole argument","If building the string in code, ensure you serialize a dict, not a list/scalar"],"exampleFix":"# before\ncrewai run --inputs '[\"topic\", \"AI\"]'\n# after\ncrewai run --inputs '{\"topic\": \"AI\"}'","handlingStrategy":"type-guard","validationCode":"import json\n\ndef inputs_is_object(s: str | None) -> bool:\n    if s is None:\n        return True\n    try:\n        return isinstance(json.loads(s), dict)\n    except json.JSONDecodeError:\n        return False","typeGuard":"def is_json_object(s: str) -> bool:\n    import json\n    try:\n        return isinstance(json.loads(s), dict)\n    except json.JSONDecodeError:\n        return False","tryCatchPattern":null,"preventionTips":["Pass a named-key object, never a bare array or string","Serialize a dict variable, not a list, when building --inputs in code","Remember the root must be an object; nested arrays as values are fine"],"tags":["cli","json","validation","inputs"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}