rohitg00/ai-engineering-from-scratch · error · ValueError

policy root must be an object

Error message

policy root must be an object

What it means

Raised in load_policy when the parsed policy document's root is not a JSON object. The action-policy loader indexes into top-level keys (humanApproval rules, tool configs), so any non-object root (array, string, number) means the policy file is malformed and every subsequent lookup would fail anyway.

Solutions

  1. Fix the policy JSON so the root is an object mapping policy sections to their configs
  2. Check the file was not truncated or overwritten with diagnostic output
  3. Add a schema check right after json.load so policy drift is caught at load time in tests
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at certifications/claude/lessons/12-claude-agent-sdk-and-hooks/code/main.py:305 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/e0fffe9af0b57648. Report an issue: GitHub.

Appendix: source

Thrown at certifications/claude/lessons/12-claude-agent-sdk-and-hooks/code/main.py:305

                return {"allowed": False, "reason": "coordinate is outside the displayed screenshot"}

        approval = self.config["humanApproval"]
        if trusted_risk_class in approval["deniedRiskClasses"]:
            return {"allowed": False, "reason": "risk class is denied"}
        if trusted_risk_class in approval["requiredRiskClasses"] and not approved:
            return {"allowed": False, "reason": "human approval required"}
        if trusted_risk_class not in approval["allowedRiskClasses"] and trusted_risk_class not in approval["requiredRiskClasses"]:
            return {"allowed": False, "reason": "unknown trusted risk class"}

        self.screenshot_id = None
        self.needs_verification = True
        return {"allowed": True, "reason": "action passed policy; capture a verification screenshot"}


def load_policy(path: Path) -> dict[str, Any]:
    value = json.loads(path.read_text(encoding="utf-8"))
    if not isinstance(value, dict):
        raise ValueError("policy root must be an object")
    return value


if __name__ == "__main__":
    path = Path(__file__).parents[1] / "outputs" / "agent-harness-policy.json"
    policy = load_policy(path)
    fixture = load_policy(Path(__file__).parents[1] / "outputs" / "managed-agent-event-fixture.json")
    checkpoint = fixture["events"][: fixture["checkpoint_after"]]
    print(
        json.dumps(
            {
                "valid": not validate_policy(policy),
                "read": evaluate_action(policy, "Read", False),
                "editWithoutApproval": evaluate_action(policy, "Edit", False),
                "managedCheckpoint": consume_managed_events(checkpoint).to_dict(),
                "managedComplete": consume_managed_events(fixture["events"]).to_dict(),
            },
            indent=2,

View on GitHub (pinned to 39ea8a1c6d)