HKUDS/Vibe-Trading · error · ValueError
audit rows must be objects
Error message
audit rows must be objects
What it means
After confirming audit is a list, each element must be a JSON object (dict) mapping criterion_id/result/evidence_ids/notes. Non-dict elements such as strings, numbers, or nested lists raise this. It is row-level schema enforcement for the goal tool's audit trail.
Source
Thrown at agent/src/tools/goal_tool.py:47
return [value] if value.strip() else []
if isinstance(value, list):
return [str(item).strip() for item in value if str(item).strip()]
return []
def _coerce_audit_rows(value: Any) -> list[AuditRow]:
"""Coerce model/API-style audit rows into dataclasses."""
if value in (None, ""):
return []
if isinstance(value, str):
value = json.loads(value)
if not isinstance(value, list):
raise ValueError("audit must be a list")
rows: list[AuditRow] = []
for item in value:
if not isinstance(item, dict):
raise ValueError("audit rows must be objects")
criterion_id = str(item.get("criterion_id") or "").strip()
result = str(item.get("result") or "").strip()
if not criterion_id or not result:
raise ValueError("audit rows require criterion_id and result")
rows.append(
AuditRow(
criterion_id=criterion_id,
result=result,
evidence_ids=_coerce_string_list(item.get("evidence_ids")),
notes=str(item.get("notes") or ""),
)
)
return rows
def _sha256_file(path: Path) -> str:
"""Return the sha256 digest for a local artifact."""
digest = hashlib.sha256()View on GitHub (pinned to 80ffdda44c)
Solutions
- Ensure every element is a dict with at least criterion_id and result keys
- json.loads twice if elements arrived as JSON strings: audit=[json.loads(x) for x in audit]
- Validate the payload shape before calling execute
Example fix
# before
execute(audit=["c1:pass"])
# after
execute(audit=[{"criterion_id": "c1", "result": "pass"}]) Defensive patterns
Strategy: validation
Validate before calling
rows = [json.loads(x) if isinstance(x, str) else x for x in audit] assert all(isinstance(r, dict) for r in rows), "audit rows must be dicts"
Type guard
def all_rows_are_objects(audit: list) -> bool:
return all(isinstance(r, dict) for r in audit) Try / catch
try:
execute(audit=audit)
except ValueError as e:
if "must be objects" in str(e):
audit = [json.loads(r) for r in audit if isinstance(r, str)]
execute(audit=audit)
raise Prevention
- Double-decode stringified rows
- Validate with a schema (pydantic) before calling the tool
When it happens
Trigger: audit=["pass", "fail"] or audit=[[{...}]] where elements are strings or nested arrays instead of objects.
Common situations: LLM emitting CSV-like rows, double-encoded JSON strings inside the list, or mixed content from template fills.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- audit must be a list
- audit rows require criterion_id and result
- legs must be a non-empty array
- invalid alpha_id
- alpha_id not found
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/64bcdda002f29343.
Report an issue: GitHub.