affaan-m/ECC · error · ValueError

Missing required field {e} at line {i}

Error message

Missing required field {e} at line {i}

What it means

Each JSONL observation record must contain the keys timestamp, event, tool, and session (input and output default to ''). When one is missing, the ObservationEvent construction raises KeyError, which is wrapped as ValueError naming the missing field and the line number.

Source

Thrown at skills/skill-comply/scripts/parser.py:72

        return []

    events: list[ObservationEvent] = []
    for i, line in enumerate(text.splitlines(), 1):
        try:
            raw = json.loads(line)
        except json.JSONDecodeError as e:
            raise ValueError(f"Invalid JSON at line {i}: {e}") from e
        try:
            events.append(ObservationEvent(
                timestamp=raw["timestamp"],
                event=raw["event"],
                tool=raw["tool"],
                session=raw["session"],
                input=raw.get("input", ""),
                output=raw.get("output", ""),
            ))
        except KeyError as e:
            raise ValueError(f"Missing required field {e} at line {i}") from e

    return sorted(events, key=lambda e: e.timestamp)


def parse_spec(path: Path) -> ComplianceSpec:
    """Parse a YAML compliance spec file."""
    if not path.is_file():
        raise FileNotFoundError(f"Spec file not found: {path}")
    raw = yaml.safe_load(path.read_text())

    steps: list[Step] = []
    for s in raw["steps"]:
        d = s["detector"]
        steps.append(Step(
            id=s["id"],
            description=s["description"],
            required=s["required"],
            detector=Detector(

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Inspect the named field and line number in the message and fix the source record.
  2. If the producer uses different key names, normalize records before write (alias session_id -> session).
  3. Run a small jsonschema check over the first record of the trace to catch schema drift early.
  4. Regenerate the trace from runner.run_scenario so it matches the parser's expected schema.

Example fix

# before (producer emits session_id)
# {"timestamp":"T0001","event":"tool_complete","tool":"Read","session_id":"abc"}

# after (normalize before writing the JSONL)
record = {"timestamp": ts, "event": ev, "tool": tool, "session": sid, "input": inp, "output": out}
fout.write(json.dumps(record) + '\n')
Defensive patterns

Strategy: validation

Validate before calling

import json
from pathlib import Path

REQUIRED = {'timestamp', 'event', 'tool', 'session'}
def validate_trace_schema(path: Path) -> list[tuple[int, set[str]]]:
    missing: list[tuple[int, set[str]]] = []
    for i, line in enumerate(path.read_text().splitlines(), 1):
        line = line.strip()
        if not line:
            continue
        keys = set(json.loads(line))
        gap = REQUIRED - keys
        if gap:
            missing.append((i, gap))
    return missing

Try / catch

from scripts.parser import parse_trace
try:
    events = parse_trace(path)
except ValueError as e:
    if 'Missing required field' in str(e):
        # identify and drop/repair the offending record
        raise

Prevention

When it happens

Trigger: A trace producer omits one of the required keys; a renamed field (e.g. 'session_id' instead of 'session') reaches the parser; a manually edited trace line drops a key.

Common situations: An upstream schema change in the stream-json adapter (_parse_stream_json) that emits a different key name; third-party tools writing a 'compatible' JSONL with subtly different field names.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/9a490c214563a2d8. Report an issue: GitHub.