bmad-code-org/BMAD-METHOD · error · ValueError
each --extra entry must be a JSON object, got: {item!r}
Error message
each --extra entry must be a JSON object, got: {item!r} What it means
After confirming the `--extra` overlay is a list, pick_methods.py iterates each element and requires every one to be a JSON object. This error names the offending element via `{item!r}`. It guards the next line, which calls `item.get(k)` for each field in FIELDS — only dicts have `.get`. A scalar or null element would otherwise raise an `AttributeError` deep in the merge.
Source
Thrown at src/core-skills/bmad-advanced-elicitation/scripts/pick_methods.py:65
with open(file, newline="", encoding="utf-8-sig") as f:
rows = list(csv.DictReader(f))
for r in rows:
for k in FIELDS:
r.setdefault(k, "")
r[k] = (r.get(k) or "").strip()
return rows
def load_extra(spec: str) -> list[dict]:
"""Parse the --extra overlay: a JSON array literal or a path to a JSON file."""
text = spec if spec.lstrip().startswith("[") else Path(spec).read_text(encoding="utf-8-sig")
data = json.loads(text)
if not isinstance(data, list):
raise ValueError("--extra must be a JSON array of objects")
rows = []
for item in data:
if not isinstance(item, dict):
raise ValueError(f"each --extra entry must be a JSON object, got: {item!r}")
row = {k: str(item.get(k) or "").strip() for k in FIELDS}
row["code"] = str(item.get("code") or "").strip() # kept for traceability
rows.append(row)
return rows
def merge_extra(rows: list[dict], extras: list[dict]) -> list[dict]:
"""Extras replace a catalog row with the same method_name (case-insensitive),
otherwise append — so overrides can retune shipped methods or grow the catalog.
A replacement inherits the shipped row's num; appended extras get the next
free nums, so every merged method stays addressable by number."""
merged = list(rows)
index = {r["method_name"].lower(): i for i, r in enumerate(merged)}
for e in extras:
key = e["method_name"].lower()
if key in index:
e = dict(e)
e["num"] = e["num"] or merged[index[key]]["num"]View on GitHub (pinned to b70486b9bd)
Solutions
- Read the `{item!r}` value in the message and wrap that element in an object with at least `method_name`, `category`, `description`, and `output_pattern`.
- Run the file through `python -c "import json,sys;[print(type(x).__name__,x) for x in json.load(open(sys.argv[1]))]" methods.json` to spot any non-dict element.
- Regenerate the overlay from a typed source (CSV/typed config) rather than hand-editing JSON.
Example fix
# before
[
"Devil's Advocate",
{"method_name":"Six Hats","category":"..."}
]
# after
[
{"method_name":"Devil's Advocate","category":"challenge","description":"...","output_pattern":"..."},
{"method_name":"Six Hats","category":"...","description":"...","output_pattern":"..."}
] Defensive patterns
Strategy: type-guard
Validate before calling
import json
data = json.loads(spec)
assert isinstance(data, list) and all(isinstance(x, dict) for x in data), \
'each --extra entry must be a JSON object' Type guard
def is_object_array(v: object) -> bool:
return isinstance(v, list) and all(isinstance(x, dict) for x in v) Try / catch
try:
extras = load_extra(args.extra)
except ValueError as e:
print(f"error: {e}", file=sys.stderr); sys.exit(2) Prevention
- Lint each element type before running the command.
- Author overlays with a typed/schema tool rather than free text.
- Run the overlay through a JSON schema that requires array-of-object.
When it happens
Trigger: The overlay array contains a bare string, number, boolean, or null among the objects: `["Six Hats", {"method_name":"..."}]`, or a trailing comma / JSON5-style element that deserializes to null.
Common situations: Appending a free-text note into the array by mistake; a truncated copy-paste that drops the braces off one entry; a generator that emits method names as strings instead of objects.
Related errors
- --extra must be a JSON array of objects
- --extra must be a JSON array of objects
- each --extra entry must be a JSON object, got: {item!r}
- unparseable date: {raw!r} (want YYYY[-MM[-DD]])
- keyed array identifier `{candidate}` must not be empty
AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13).
Data as JSON: /api/errors/fc1f4cb40556dd0e.
Report an issue: GitHub.