{"record":{"id":"bf7a613933cef6b7","repo":"Hmbown/CodeWhale","slug":"cargo-metadata-root-must-be-an-object","errorCode":null,"errorMessage":"Cargo metadata root must be an object","messagePattern":"Cargo metadata root must be an object","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"scripts/release/validate-crate-publish-order.py","lineNumber":58,"sourceCode":"            [\"cargo\", \"metadata\", \"--locked\", \"--format-version\", \"1\", \"--no-deps\"],\n            check=False,\n            capture_output=True,\n            text=True,\n        )\n        if process.returncode != 0:\n            detail = process.stderr.strip()\n            suffix = f\": {detail}\" if detail else \"\"\n            raise ValidationError(\n                f\"cargo metadata failed with exit code {process.returncode}{suffix}\"\n            )\n        raw = process.stdout\n\n    try:\n        metadata = json.loads(raw)\n    except json.JSONDecodeError as error:\n        raise ValidationError(f\"Cargo metadata is not valid JSON: {error}\") from error\n    if not isinstance(metadata, dict):\n        raise ValidationError(\"Cargo metadata root must be an object\")\n    return metadata\n\n\ndef workspace_packages(metadata: dict[str, Any]) -> list[dict[str, Any]]:\n    members = metadata.get(\"workspace_members\")\n    packages = metadata.get(\"packages\")\n    if not isinstance(members, list) or not isinstance(packages, list):\n        raise ValidationError(\"Cargo metadata must contain workspace_members and packages lists\")\n\n    packages_by_id = {\n        package.get(\"id\"): package\n        for package in packages\n        if isinstance(package, dict) and isinstance(package.get(\"id\"), str)\n    }\n    missing_ids = [member for member in members if member not in packages_by_id]\n    if missing_ids:\n        raise ValidationError(\n            \"Cargo metadata omits workspace package ids: \" + \", \".join(missing_ids)","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/scripts/release/validate-crate-publish-order.py#L40-L76","documentation":"After JSON parsing succeeds, load_metadata checks that the decoded cargo metadata is a dict (JSON object) and raises this ValidationError otherwise. cargo metadata is specified to emit a top-level object, so anything else indicates a corrupt or substituted input.","triggerScenarios":"The metadata file contains a JSON array, string, number, or null instead of an object — e.g. someone stored just the packages list, or a pipeline step wrote `[]` on empty output.","commonSituations":"A downstream script extracted metadata['packages'] and saved only that fragment; a mock/test fixture file with the wrong shape; an empty-output placeholder written by a failed step.","solutions":["Regenerate the full cargo metadata JSON object (do not save only sub-fields): cargo metadata --locked --format-version 1 --no-deps","Omit the file argument to let the script obtain metadata itself","Inspect the first characters of the file — it must start with '{'","Fix the pipeline step that produces the file to write the complete object"],"exampleFix":"// before (fragment saved)\njson.dump(metadata[\"packages\"], f)\n// after\njson.dump(metadata, f)  # full cargo metadata object","handlingStrategy":"validation","validationCode":"import json\nm = json.load(open(\"cargo-metadata.json\"))\nif not isinstance(m, dict):\n    raise SystemExit(\"metadata must be a top-level JSON object; save full cargo metadata output\")","typeGuard":"def is_cargo_metadata(value) -> bool:\n    return isinstance(value, dict)","tryCatchPattern":"try:\n    validate_publish_order(metadata_file)\nexcept ValidationError as e:\n    if \"root must be an object\" in str(e):\n        print(\"the file is a JSON fragment; write the full metadata object\")","preventionTips":["Never save sub-objects (e.g. only packages) as the metadata artifact","Assert the artifact starts with '{' in pipeline steps that produce it","Validate fixtures against the real cargo metadata shape"],"tags":["python","json","validation","cargo"],"backgroundTag":"schema-validation-failed","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"}