BoundaryML/baml · error · StreamingError

Expected to encounter a class

Error message

Expected to encounter a class

What it means

StreamingError::ExpectedClass is raised during semantic streaming validation when the validator expects to inspect a class-typed value but encounters a different kind of node. This means the streamed value's type does not match the class shape the streaming machinery assumes. It is part of the jsonish deserializer's streaming-consistency checks.

Source

Thrown at engine/baml-lib/jsonish/src/deserializer/semantic_streaming.rs:22

use std::collections::HashSet;

use anyhow::{Context, Error};
use baml_types::{
    BamlMap, BamlValueWithMeta, Completion, CompletionState, ResponseCheck, TypeIR, TypeValue,
};
use indexmap::{IndexMap, IndexSet};
use internal_baml_core::ir::{
    ir_helpers::infer_type_with_meta,
    repr::{IntermediateRepr, Walker},
    Field, IRHelper, IRHelperExtended, IRSemanticStreamingHelper,
};
use thiserror;

use crate::{deserializer::coercer::ParsingError, BamlValueWithFlags, Flag};

#[derive(Debug, thiserror::Error)]
pub enum StreamingError {
    #[error("Expected to encounter a class")]
    ExpectedClass,
    #[error("Value was marked Done, but was incomplete in the stream")]
    IncompleteDoneValue,
    #[error("Class instance did not contain fields marked as needed: {fields:?}")]
    MissingNeededFields { fields: Vec<String> },
    #[error("Failed to distribute_type_with_meta: {0}")]
    DistributeTypeWithMetaFailure(#[from] anyhow::Error),
}

/// For a given baml value, traverse its nodes, comparing the completion state
/// of each node against the streaming behavior of the node's type.
pub fn validate_streaming_state(
    ir: &impl IRHelperExtended,
    baml_value: &BamlValueWithFlags,
    mode: baml_types::StreamingMode,
) -> Result<BamlValueWithMeta<Completion>, StreamingError> {
    let baml_value_with_meta_flags: BamlValueWithMeta<Vec<Flag>> = baml_value.clone().into();
    let typed_baml_value: BamlValueWithMeta<(Vec<Flag>, TypeIR)> =

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Check the BAML function's return type is a class and the prompt clearly instructs JSON object output.
  2. Inspect the raw LLM stream to see whether the model emitted a non-object (array/scalar) response.
  3. If using a union type, ensure the streaming validator handles which branch was chosen; add schema/prompt constraints to disambiguate.
  4. Wrap deserialization in error handling that logs the offending partial value for debugging.

Example fix

// before: prompt allows bare array output
// after: constrain the function return
// function Extract() -> MySchema { ... }  // MySchema is a class, not an array
Defensive patterns

Strategy: try-catch

Validate before calling

// validate expected shape before semantic streaming validation
if !matches!(expected_type, TypeIR::Class(_)) {
    return Err(anyhow::anyhow!("function must return a class for streaming validation"));
}

Type guard

fn is_class_value(v: &BamlValueWithFlags) -> bool { matches!(v, BamlValueWithFlags::Class(_)) }

Try / catch

match validate_streaming_state(&value) {
    Err(StreamingError::ExpectedClass) => inspect_and_log_raw_stream(&raw),
    Err(e) => return Err(e.into()),
    Ok(()) => finish(),
}

Prevention

When it happens

Trigger: validate_streaming_state (or the class-field distributor) reaches a value whose corresponding BAML type is not a class while trying to enumerate class fields — e.g. the LLM produced a bare string/array where a class was expected, or type distribution picked a non-class variant.

Common situations: Model outputting a JSON array or scalar instead of the requested object; a union return type where the streamed branch resolved to a non-class; mismatch between prompt instructions and the declared return type.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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