{"record":{"id":"bc8131ae572aa33f","repo":"BoundaryML/baml","slug":"class-instance-did-not-contain-fields-marked-as-needed","errorCode":null,"errorMessage":"Class instance did not contain fields marked as needed: {fields:?}","messagePattern":"Class instance did not contain fields marked as needed: (.+?)","errorType":"exception","errorClass":"StreamingError","httpStatus":null,"severity":"error","filePath":"engine/baml-lib/jsonish/src/deserializer/semantic_streaming.rs","lineNumber":26,"sourceCode":"    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)> =\n        ir.distribute_type_with_meta(baml_value_with_meta_flags, baml_value.field_type().clone())?;\n    let baml_value_with_streaming_state_and_behavior =\n        typed_baml_value.map_meta(|(flags, r#type)| (completion_state(flags), r#type));\n","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/jsonish/src/deserializer/semantic_streaming.rs#L8-L44","documentation":"StreamingError::MissingNeededFields fires when a streamed class instance is considered complete but lacks fields whose streaming_behavior marks them as needed. BAML lets fields be declared 'needed' for streaming correctness; a Done value missing them violates that contract.","triggerScenarios":"validate_streaming_state finishes traversal on a class node marked Done while one or more fields with streaming_needed=true never appeared or never completed in the stream.","commonSituations":"Model omitted a required field in its JSON output; field declared with @stream.done or needed semantics but the model never emits it; truncation dropping trailing fields.","solutions":["Review which fields are marked needed in the class's streaming behavior and confirm the prompt asks for all of them.","Increase max_tokens or adjust stop conditions so the model can emit every field.","Make the field optional in the schema if it is not truly required.","Retry the generation; log the missing field names from the error for prompt iteration."],"exampleFix":"// before: field required but often missing\nclass Resume { name string @stream.needed  skills string[] @stream.needed }\n// after: relax if optional\nclass Resume { name string  skills string[]? }","handlingStrategy":"validation","validationCode":"// after streaming completes, verify needed fields present\nfor f in needed_fields_of(class_type) {\n    if !value_has_field(&value, &f.name) {\n        return Err(anyhow::anyhow!(\"needed field missing: {}\", f.name));\n    }\n}","typeGuard":"fn has_needed_fields(v: &BamlValueWithFlags, needed: &[String]) -> bool {\n    needed.iter().all(|f| v.field(f).map(|x| x.is_done()).unwrap_or(false))\n}","tryCatchPattern":"match validate_streaming_state(&value) {\n    Err(StreamingError::MissingNeededFields { fields }) => {\n        log::warn!(\"model omitted needed fields: {fields:?}\");\n        retry_with_reinforced_prompt(&fields).await?\n    }\n    other => other?,\n}","preventionTips":["Only mark fields as needed when the prompt reliably elicits them","Reinforce required fields in the prompt with explicit JSON schema examples","Make rarely-emitted fields optional in the schema","Log missing field lists to iterate on prompts"],"tags":["rust","streaming","missing-field","schema"],"backgroundTag":"schema-validation-failed","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"}