{"record":{"id":"c2609820ae61b57a","repo":"Hmbown/CodeWhale","slug":"invalid-kind-path-top-level-must-be-an-object","errorCode":null,"errorMessage":"invalid {kind} {path}: top level must be an object","messagePattern":"invalid (.+?) (.+?): top level must be an object","errorType":"console","errorClass":"RuntimeContractError","httpStatus":null,"severity":"error","filePath":"scripts/check-runtime-contract-budget.py","lineNumber":168,"sourceCode":"        )\n        for stage, label in REPRESENTATIVE_STAGES\n    ),\n)\n\n\nclass RuntimeContractError(ValueError):\n    \"\"\"A receipt or budget is missing a required, well-typed metric.\"\"\"\n\n\ndef load_json(path: Path, kind: str) -> dict[str, Any]:\n    try:\n        document = json.loads(path.read_text(encoding=\"utf-8\"))\n    except FileNotFoundError as error:\n        raise RuntimeContractError(f\"missing {kind}: {path}\") from error\n    except (OSError, json.JSONDecodeError) as error:\n        raise RuntimeContractError(f\"invalid {kind} {path}: {error}\") from error\n    if not isinstance(document, dict):\n        raise RuntimeContractError(f\"invalid {kind} {path}: top level must be an object\")\n    return document\n\n\ndef validate_document(\n    document: dict[str, Any], expected_kind: str, source: str\n) -> None:\n    actual_kind = document.get(\"document_kind\")\n    if actual_kind != expected_kind:\n        raise RuntimeContractError(\n            f\"{source} document_kind must be `{expected_kind}`, got {actual_kind!r}\"\n        )\n    version = document.get(\"schema_version\")\n    if (\n        isinstance(version, bool)\n        or not isinstance(version, int)\n        or version != SCHEMA_VERSION\n    ):\n        raise RuntimeContractError(","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/scripts/check-runtime-contract-budget.py#L150-L186","documentation":"After successfully parsing the JSON, load_json requires the top-level value to be a JSON object (dict). Arrays, strings, numbers, or null at the top level raise this RuntimeContractError, because receipt and budget documents are always objects with document_kind/schema_version fields.","triggerScenarios":"Passing a --receipt file whose content is a JSON array, string, number, boolean, or null — e.g. a file holding `[1,2,3]`, a list of receipts, or `null` from a failed serialization.","commonSituations":"A tool wrote a JSON array of results instead of a single object; a placeholder or test fixture file was pointed at; a script serialized the wrong variable.","solutions":["Open the file and confirm the top level is `{...}`; wrap the value in an object if the producer wrote an array or scalar.","Fix the producer so it emits a single receipt/budget object with document_kind and schema_version fields.","Point --receipt at the correct per-run receipt file rather than an aggregate list."],"exampleFix":"// before (receipt.json)\n[{\"document_kind\": \"codewhale.runtime_contract_receipt\"}]\n// after\n{\"document_kind\": \"codewhale.runtime_contract_receipt\", \"schema_version\": 1}","handlingStrategy":"type-guard","validationCode":"import json\nfrom pathlib import Path\ndoc = json.loads(Path(path).read_text(encoding=\"utf-8\"))\nif not isinstance(doc, dict):\n    raise SystemExit(f\"{path}: top level must be a JSON object\")","typeGuard":"def is_receipt_object(path) -> bool:\n    import json\n    from pathlib import Path\n    try:\n        return isinstance(json.loads(Path(path).read_text(encoding=\"utf-8\")), dict)\n    except Exception:\n        return False","tryCatchPattern":"try:\n    doc = load_json(path, \"receipt\")\nexcept RuntimeContractError as e:\n    if \"top level must be an object\" in str(e):\n        print(f\"{path} holds a non-object JSON value; fix the producer\")\n    raise","preventionTips":["Producers must serialize a single receipt/budget object, never a bare list or scalar.","Sanity-check generated files by asserting `isinstance(doc, dict)` right after writing.","Keep placeholder/fixture JSON files shaped like real documents."],"tags":["python","json","schema","validation"],"backgroundTag":"unexpected-response-shape","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}