BoundaryML/baml · error

run started record omitted time anchor

Error message

run started record omitted time anchor

What it means

Thrown by TryFrom<pb::RunStartedV1> for RunStartedRecord when the protobuf message lacks `time_anchor` (the timestamp/anchor field). The record type requires it so all run events can be ordered against a common clock; a missing anchor makes the record unusable, so the conversion returns io::ErrorKind::InvalidData.

Source

Thrown at baml_language/crates/bex_events/src/value/record.rs:412

            call: value.call.map(Into::into),
            message: value.message.clone(),
            timestamp_ms: value.timestamp_ms,
        }
    }
}

impl TryFrom<crate::value::pb::RunStartedV1> for RunStartedRecord {
    type Error = io::Error;

    fn try_from(value: crate::value::pb::RunStartedV1) -> Result<Self, Self::Error> {
        let target = value.target.ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::InvalidData,
                "run started record omitted target",
            )
        })?;
        let time_anchor = value.time_anchor.ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::InvalidData,
                "run started record omitted time anchor",
            )
        })?;
        Ok(Self {
            request: RunRequestSummary {
                project_id: ProjectId(value.project_id),
                project_generation: ProjectGeneration(value.project_generation),
                target: run_target_from_proto(target)?,
                args_summary: value.args_summary,
                options_summary: value.options_summary,
            },
            created_at_ms: value.created_at_ms,
            time_anchor: RunTimeAnchor {
                epoch_created_at_ms: time_anchor.epoch_created_at_ms,
                trace_zero_ns: time_anchor.trace_zero_ns,
            },
        })

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Set time_anchor (set_time_anchor(pb::TimeAnchor{...})) on RunStartedV1 before serializing
  2. Audit the emitter that created the event to ensure it records the time anchor
  3. Reject or quarantine malformed records at decode time instead of failing the whole stream
  4. Check schema versions between producer and consumer for dropped fields

Example fix

// before
let rec = RunStartedRecord::try_from(msg)?; // time_anchor None
// after
msg.time_anchor = Some(pb::TimeAnchor { unix_nanos: now_ns });
let rec = RunStartedRecord::try_from(msg)?;
Defensive patterns

Strategy: validation

Validate before calling

fn has_anchor(msg: &pb::RunStartedV1) -> bool { msg.time_anchor.is_some() }

Type guard

fn time_anchor(msg: &pb::RunStartedV1) -> Option<&pb::TimeAnchor> { msg.time_anchor.as_ref() }

Try / catch

match RunStartedRecord::try_from(msg) {
    Ok(rec) => rec,
    Err(e) if e.kind() == io::ErrorKind::InvalidData => { log::warn!("run-started missing anchor: {e}"); Default::default() },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: RunStartedRecord::try_from on a RunStartedV1 whose time_anchor field is None — either never set by the producer or dropped during (de)serialization of the event stream.

Common situations: Producer code updated to a new schema where time_anchor moved/renamed and old emitters no longer populate it; fixtures that set target but forget time_anchor; clock/telemetry wiring omitted in a new run harness.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/e8b86f5ade70aa1e. Report an issue: GitHub.