BoundaryML/baml · error

run target omitted variant

Error message

run target omitted variant

What it means

run_target_from_proto converts pb::RunTargetV1 into the RunTarget domain type; it errors when the `target` oneof is None, i.e. the proto message names no concrete target variant (Function or Test). Since RunTarget is an enum with no empty case, the conversion cannot proceed and returns io::ErrorKind::InvalidData.

Solutions

  1. Populate the oneof on the producer side (set_function(...) or set_test(...))
  2. Fix the emitter to require a concrete variant before writing the event
  3. Reject/skip such records at decode time with a log entry
  4. Verify producer/consumer protobuf definitions match

Example fix

// before
let t = run_target_from_proto(pb::RunTargetV1::default())?; // oneof unset
// after
let t = run_target_from_proto(pb::RunTargetV1 {
    target: Some(pb::run_target_v1::Target::Function(pb::FunctionTarget { function_name: "f".into() })),
})?;
Defensive patterns

Strategy: validation

Validate before calling

fn has_variant(v: &pb::RunTargetV1) -> bool { v.target.is_some() }

Type guard

fn as_target(v: pb::RunTargetV1) -> Option<pb::run_target_v1::Target> { v.target }

Try / catch

match run_target_from_proto(msg) {
    Ok(t) => t,
    Err(e) if e.kind() == io::ErrorKind::InvalidData => { log::warn!("run target oneof unset"); RunTarget::default() },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling run_target_from_proto on a RunTargetV1 decoded without its oneof set (producer never called set_target), or a message whose variant tag was lost in transport/storage.

Common situations: Hand-built test messages missing the oneof; a producer/schema change where the variant field was renamed; partially written event-stream bytes.

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/32046c58a6a6cf12. Report an issue: GitHub.

Appendix: source

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

impl From<&RunCompletedRecord> for crate::value::pb::RunCompletedV1 {
    fn from(value: &RunCompletedRecord) -> Self {
        Self {
            status: run_status_to_proto(value.status) as i32,
            completed_at_ms: value.completed_at_ms,
            renderer_hint: value.renderer_hint.clone(),
            result_value_ref: value.result_value_ref.as_ref().map(Into::into),
            error: value.error.as_ref().map(run_error_to_proto),
            cancellation: value.cancellation.as_ref().map(cancellation_to_proto),
        }
    }
}

fn run_target_from_proto(value: crate::value::pb::RunTargetV1) -> io::Result<RunTarget> {
    use crate::value::pb::run_target_v1::Target;
    match value
        .target
        .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "run target omitted variant"))?
    {
        Target::Function(target) => Ok(RunTarget::Function {
            function_name: target.function_name,
        }),
        Target::Test(target) => Ok(RunTarget::Test {
            generation: ProjectGeneration(target.generation),
            test_name: target.test_name,
        }),
        Target::Preview(target) => Ok(RunTarget::Preview {
            parent_function_name: target.parent_function_name,
            helper: target.helper,
        }),
        Target::Companion(target) => {
            let parent_boundary_id = target
                .parent_boundary_id
                .as_deref()
                .map(boundary_id_from_slice)
                .transpose()?;

View on GitHub (pinned to bd85ce9dee)