BoundaryML/baml · error

run completed record omitted status

Error message

run completed record omitted status

What it means

Thrown by TryFrom<pb::RunCompletedV1> for the run completed record when the run status proto enum is UNSPECIFIED. Every completed-run record must carry a concrete status (Succeeded/Failed/Cancelled/Panicked/Cancelling); UNSPECIFIED is the proto3 default meaning the producer never set the field, so conversion is rejected as InvalidData.

Solutions

  1. Have the producer always set status (set_status(pb::RunStatus::Succeeded) etc.) on RunCompletedV1
  2. Fix run-finish code paths so the terminal status is recorded before the event is emitted
  3. Treat UNSPECIFIED at decode time as a malformed record and skip/log it
  4. Add a producer-side assertion that status != Unspecified before serializing

Example fix

// before
let rec = RunCompletedRecord::try_from(msg)?; // status Unspecified
// after
msg.status = pb::RunStatus::Failed as i32; // or set_status(...)
let rec = RunCompletedRecord::try_from(msg)?;
Defensive patterns

Strategy: validation

Validate before calling

fn has_status(msg: &pb::RunCompletedV1) -> bool {
    msg.status != pb::RunStatus::Unspecified as i32
}

Try / catch

match RunCompletedRecord::try_from(msg) {
    Ok(rec) => rec,
    Err(e) if e.kind() == io::ErrorKind::InvalidData => { log::warn!("run-completed missing status: {e}"); return; },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: RunCompletedRecord::try_from on a message where `status` was left at its default UNSPECIFIED — the emitter forgot set_status(), or the value was zeroed out during serialization/storage.

Common situations: Prost/proto3 default-value pitfalls (enum defaulting to 0/UNSPECIFIED when unset); a new completion path in the runner that reports status late; corrupted event records.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

    }
}

impl TryFrom<crate::value::pb::RunCompletedV1> for RunCompletedRecord {
    type Error = io::Error;

    fn try_from(value: crate::value::pb::RunCompletedV1) -> Result<Self, Self::Error> {
        let status = match value.status() {
            crate::value::pb::RunStatus::Pending => RunStatus::Pending,
            crate::value::pb::RunStatus::Running => RunStatus::Running,
            crate::value::pb::RunStatus::WaitingForInput => RunStatus::WaitingForInput,
            crate::value::pb::RunStatus::WaitingForEnv => RunStatus::WaitingForEnv,
            crate::value::pb::RunStatus::Cancelling => RunStatus::Cancelling,
            crate::value::pb::RunStatus::Succeeded => RunStatus::Succeeded,
            crate::value::pb::RunStatus::Failed => RunStatus::Failed,
            crate::value::pb::RunStatus::Cancelled => RunStatus::Cancelled,
            crate::value::pb::RunStatus::Panicked => RunStatus::Panicked,
            crate::value::pb::RunStatus::Unspecified => {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    "run completed record omitted status",
                ));
            }
        };
        Ok(Self {
            status,
            completed_at_ms: value.completed_at_ms,
            renderer_hint: value.renderer_hint,
            result_value_ref: value.result_value_ref.map(ValueRef::try_from).transpose()?,
            error: value.error.map(run_error_from_proto).transpose()?,
            cancellation: value.cancellation.map(cancellation_from_proto),
        })
    }
}

impl From<&RunCompletedRecord> for crate::value::pb::RunCompletedV1 {
    fn from(value: &RunCompletedRecord) -> Self {

View on GitHub (pinned to bd85ce9dee)