{"record":{"id":"8f20cf52594c47db","repo":"BoundaryML/baml","slug":"expected-to-encounter-a-class","errorCode":null,"errorMessage":"Expected to encounter a class","messagePattern":"Expected to encounter a class","errorType":"exception","errorClass":"StreamingError","httpStatus":null,"severity":"error","filePath":"engine/baml-lib/jsonish/src/deserializer/semantic_streaming.rs","lineNumber":22,"sourceCode":"use std::collections::HashSet;\n\nuse anyhow::{Context, Error};\nuse baml_types::{\n    BamlMap, BamlValueWithMeta, Completion, CompletionState, ResponseCheck, TypeIR, TypeValue,\n};\nuse indexmap::{IndexMap, IndexSet};\nuse internal_baml_core::ir::{\n    ir_helpers::infer_type_with_meta,\n    repr::{IntermediateRepr, Walker},\n    Field, IRHelper, IRHelperExtended, IRSemanticStreamingHelper,\n};\nuse thiserror;\n\nuse crate::{deserializer::coercer::ParsingError, BamlValueWithFlags, Flag};\n\n#[derive(Debug, thiserror::Error)]\npub enum StreamingError {\n    #[error(\"Expected to encounter a class\")]\n    ExpectedClass,\n    #[error(\"Value was marked Done, but was incomplete in the stream\")]\n    IncompleteDoneValue,\n    #[error(\"Class instance did not contain fields marked as needed: {fields:?}\")]\n    MissingNeededFields { fields: Vec<String> },\n    #[error(\"Failed to distribute_type_with_meta: {0}\")]\n    DistributeTypeWithMetaFailure(#[from] anyhow::Error),\n}\n\n/// For a given baml value, traverse its nodes, comparing the completion state\n/// of each node against the streaming behavior of the node's type.\npub fn validate_streaming_state(\n    ir: &impl IRHelperExtended,\n    baml_value: &BamlValueWithFlags,\n    mode: baml_types::StreamingMode,\n) -> Result<BamlValueWithMeta<Completion>, StreamingError> {\n    let baml_value_with_meta_flags: BamlValueWithMeta<Vec<Flag>> = baml_value.clone().into();\n    let typed_baml_value: BamlValueWithMeta<(Vec<Flag>, TypeIR)> =","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/jsonish/src/deserializer/semantic_streaming.rs#L4-L40","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the BAML function's return type is a class and the prompt clearly instructs JSON object output.","Inspect the raw LLM stream to see whether the model emitted a non-object (array/scalar) response.","If using a union type, ensure the streaming validator handles which branch was chosen; add schema/prompt constraints to disambiguate.","Wrap deserialization in error handling that logs the offending partial value for debugging."],"exampleFix":"// before: prompt allows bare array output\n// after: constrain the function return\n// function Extract() -> MySchema { ... }  // MySchema is a class, not an array","handlingStrategy":"try-catch","validationCode":"// validate expected shape before semantic streaming validation\nif !matches!(expected_type, TypeIR::Class(_)) {\n    return Err(anyhow::anyhow!(\"function must return a class for streaming validation\"));\n}","typeGuard":"fn is_class_value(v: &BamlValueWithFlags) -> bool { matches!(v, BamlValueWithFlags::Class(_)) }","tryCatchPattern":"match validate_streaming_state(&value) {\n    Err(StreamingError::ExpectedClass) => inspect_and_log_raw_stream(&raw),\n    Err(e) => return Err(e.into()),\n    Ok(()) => finish(),\n}","preventionTips":["Declare class return types explicitly in BAML functions","Instruct the model to emit a JSON object, never bare arrays/scalars","Log raw streams when type-shaped errors occur to spot model drift"],"tags":["rust","streaming","deserialization","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}