{"record":{"id":"c65e47a88257ce49","repo":"HKUDS/Vibe-Trading","slug":"manifest-file-manifest-path-must-be-a-json-objec","errorCode":null,"errorMessage":"manifest file {manifest_path} must be a JSON object with a 'runs' array or a bare JSON array of run specs","messagePattern":"manifest file (.+?) must be a JSON object with a 'runs' array or a bare JSON array of run specs","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/strategy_discovery_tool.py","lineNumber":483,"sourceCode":"        raw = manifest_path.read_text(encoding=\"utf-8\")\n    except OSError as exc:\n        raise ValueError(\n            f\"manifest file {manifest_path} is missing or unreadable \"\n            f\"({exc.strerror or 'I/O error'})\"\n        ) from exc\n    try:\n        parsed = json.loads(raw)\n    except json.JSONDecodeError as exc:\n        raise ValueError(\n            f\"manifest file {manifest_path} is not valid JSON: {exc.msg} \"\n            f\"at line {exc.lineno} column {exc.colno}\"\n        ) from exc\n    if isinstance(parsed, list):\n        return parsed\n    if isinstance(parsed, dict):\n        runs = parsed.get(\"runs\")\n        if not isinstance(runs, list):\n            raise ValueError(\n                f\"manifest file {manifest_path} must be a JSON object with a \"\n                \"'runs' array or a bare JSON array of run specs\"\n            )\n        return runs\n    raise ValueError(\n        f\"manifest file {manifest_path} must be a JSON object with a 'runs' \"\n        \"array or a bare JSON array of run specs\"\n    )\n\n\ndef validate_refresh_entries(\n    entries: list,\n) -> tuple[list[dict], list[dict]]:\n    \"\"\"Split raw manifest entries into rebuild-ready specs and skip records.\n\n    Per-entry validation (plan §4.6/D7): the entry must be a mapping with a\n    non-empty ``strategy_id`` (capped at ``_MAX_STRING_PARAM_CHARS``) and a\n    non-empty ``run_dir`` that resolves (expanduser + resolve) inside the","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/strategy_discovery_tool.py#L465-L501","documentation":"After parsing, load_manifest expects either a bare JSON array of run specs or a JSON object containing a 'runs' key whose value is a list. This variant fires when the top level is a dict but parsed['runs'] is not a list — e.g. it's missing, an object, a string, or null. The runs list is what gets returned for validation.","triggerScenarios":"Manifest like {\"results\": [...]} (wrong key), {\"runs\": {\"a\": 1}} (object not array), or {\"runs\": null}; any dict whose 'runs' value fails isinstance(runs, list).","commonSituations":"Schema drift between manifest writers and readers (key renamed to 'experiments'); wrapping run specs in a nested object for grouping; exporting from a tool that emits runs as a dict keyed by run id.","solutions":["Rename the key to exactly \"runs\" and make its value a JSON array","If runs are keyed by id (object), flatten to a list: {\"runs\": list(your_dict.values())} or [your_dict[k] for k in sorted(your_dict)]","Check the tool's run-spec schema/docs for the expected manifest shape"],"exampleFix":"# before\n{ \"runs\": { \"r1\": {\"path\": \"...\"}, \"r2\": {\"path\": \"...\"} } }\n# after\n{ \"runs\": [ {\"path\": \"...\"}, {\"path\": \"...\"} ] }","handlingStrategy":"validation","validationCode":"import json\ndata = json.loads(Path(manifest_path).read_text(encoding=\"utf-8\"))\nruns = data if isinstance(data, list) else data.get(\"runs\") if isinstance(data, dict) else None\nif not isinstance(runs, list):\n    raise ValueError(\"manifest must be a list or {'runs': [...]}\")\ncore(manifest_path=manifest_path, ...)","typeGuard":"def has_valid_runs_shape(data) -> bool:\n    return isinstance(data, list) or (isinstance(data, dict) and isinstance(data.get(\"runs\"), list))","tryCatchPattern":null,"preventionTips":["Use the documented {\"runs\": [...]} shape in manifest writers","Flatten id-keyed run dicts to arrays before writing the manifest"],"tags":["strategy-discovery","manifest","schema-validation","json-shape"],"backgroundTag":"json-schema-shape-mismatch","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}