{"record":{"id":"b0ffc0fd3cb31692","repo":"BoundaryML/baml","slug":"ai-prompt-data-must-contain-baml-builtins2-promptast","errorCode":null,"errorMessage":"ai.Prompt._data must contain baml_builtins2::PromptAst","messagePattern":"ai\\.Prompt\\._data must contain baml_builtins2::PromptAst","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_vm/src/package_baml/prompt.rs","lineNumber":321,"sourceCode":"                && let Some(&new_ptr) = forwarding.get(&ptr)\n            {\n                *value = Value::object(new_ptr);\n            }\n        }\n        for ptr in &mut self.pending {\n            if let Some(&new_ptr) = forwarding.get(ptr) {\n                *ptr = new_ptr;\n            }\n        }\n    }\n}\n\nimpl BamlClassPrompt for PackageAiImpl {\n    fn text(vm: &BexVm, prompt: &ai_view::Prompt<'_>) -> bex_str::BexStr {\n        let data = prompt.instance.load_field(0);\n        let prompt = vm\n            .as_rust_data::<PromptAst>(&data)\n            .expect(\"ai.Prompt._data must contain baml_builtins2::PromptAst\");\n        bex_str::BexStr::from(prompt.render_text())\n    }\n\n    fn messages(vm: &mut BexVm, prompt: &Value) -> Vec<Value> {\n        let messages = {\n            let instance = vm\n                .as_instance(prompt)\n                .expect(\"ai.Prompt.messages receiver must be an ai.Prompt instance\");\n            let data = instance.load_field(0);\n            vm.as_rust_data::<PromptAst>(&data)\n                .expect(\"ai.Prompt._data must contain baml_builtins2::PromptAst\")\n                .to_structured_messages()\n        };\n        let message_class = vm.resolve_class(\"ai.PromptMessage\");\n        messages\n            .into_iter()\n            .map(|(role, content, metadata)| {\n                let role = Value::object(vm.alloc_string(role));","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_vm/src/package_baml/prompt.rs#L303-L339","documentation":"Panic in `ai.Prompt.text` when the Prompt instance's field 0 (`_data`) does not hold Rust data of type `baml_builtins2::PromptAst`. The method unconditionally downcasts the field to render the prompt as text; a failed downcast means the instance was constructed with wrong field layout or wrong data type, breaking the ai.Prompt class invariant.","triggerScenarios":"Constructing an `ai.Prompt` instance whose field 0 is not a PromptAst rust-data value — e.g. via reflection/raw value construction, a class-layout mismatch after VM upgrades, or passing a foreign instance into `ai.Prompt.text`.","commonSituations":"Embedding the VM and building Prompt instances manually, version skew between code that constructs Prompt instances and the prompt package's expected layout, or corrupted serialized class instances.","solutions":["Construct ai.Prompt only through its official constructor so field 0 receives a PromptAst.","Check that the Prompt class field layout (field 0 = _data) matches the VM's registered class definition — rebuild all crates together.","Verify the value is a PromptAst before rendering: vm.as_rust_data::<PromptAst>(&data).is_ok().","Report the misconstructed instance path to baml_language maintainers."],"exampleFix":"// before\nlet prompt = PackageAiImpl::text(&vm, &p);\n// after\nif vm.as_rust_data::<PromptAst>(&p.instance.load_field(0)).is_err() {\n    return; // or surface a proper error instead of panicking\n}\nlet prompt = PackageAiImpl::text(&vm, &p);","handlingStrategy":"type-guard","validationCode":"fn is_prompt_ast(vm: &BexVm, value: &Value) -> bool {\n    vm.as_instance(value)\n        .map(|i| vm.as_rust_data::<PromptAst>(&i.load_field(0)).is_ok())\n        .unwrap_or(false)\n}","typeGuard":"fn as_prompt<'a>(vm: &BexVm, v: &'a Value) -> Option<&'a PromptAst> {\n    vm.as_instance(v)\n        .ok()\n        .and_then(|i| vm.as_rust_data::<PromptAst>(&i.load_field(0)).ok())\n}","tryCatchPattern":"// Panic cannot be caught; guard before rendering:\nif as_prompt(&vm, &value).is_none() { /* surface proper error */ }","preventionTips":["Build ai.Prompt instances only via the official constructor.","Rebuild all crates together so the Prompt field layout stays in sync.","Never construct class instances by hand-poking field 0."],"tags":["rust","prompt","type-mismatch","panic"],"backgroundTag":"internal-invariant-violation","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"}