BoundaryML/baml · error
ai.Prompt.messages receiver must be an ai.Prompt instance
Error message
ai.Prompt.messages receiver must be an ai.Prompt instance
What it means
Panic in `ai.Prompt.messages` when the receiver value is not an `ai.Prompt` instance at all. The method calls `vm.as_instance(prompt).expect(...)` before reading field 0, so any non-instance value passed as the method receiver aborts. This guards the implicit `self` contract of the Prompt class methods.
Source
Thrown at baml_language/crates/bex_vm/src/package_baml/prompt.rs:329
}
}
}
}
impl BamlClassPrompt for PackageAiImpl {
fn text(vm: &BexVm, prompt: &ai_view::Prompt<'_>) -> bex_str::BexStr {
let data = prompt.instance.load_field(0);
let prompt = vm
.as_rust_data::<PromptAst>(&data)
.expect("ai.Prompt._data must contain baml_builtins2::PromptAst");
bex_str::BexStr::from(prompt.render_text())
}
fn messages(vm: &mut BexVm, prompt: &Value) -> Vec<Value> {
let messages = {
let instance = vm
.as_instance(prompt)
.expect("ai.Prompt.messages receiver must be an ai.Prompt instance");
let data = instance.load_field(0);
vm.as_rust_data::<PromptAst>(&data)
.expect("ai.Prompt._data must contain baml_builtins2::PromptAst")
.to_structured_messages()
};
let message_class = vm.resolve_class("ai.PromptMessage");
messages
.into_iter()
.map(|(role, content, metadata)| {
let role = Value::object(vm.alloc_string(role));
let readable = Value::object(vm.alloc_string(content.to_text()));
let parts = prompt_content_values(vm, content.as_ref());
let parts =
Value::object(vm.alloc_array(bex_vm_types::RealizedTy::unknown(), parts));
let metadata = prompt_metadata_value(vm, metadata);
Value::object(
vm.alloc_instance(message_class, vec![role, readable, parts, metadata]),
)View on GitHub (pinned to bd85ce9dee)
Solutions
- Ensure the receiver is a real ai.Prompt instance: check vm.as_instance(value).is_ok() before calling messages.
- Invoke messages via normal BAML method-call syntax so the receiver is bound automatically.
- Fix any custom dispatch code that drops or substitutes the receiver argument.
Example fix
// before
let msgs = PackageAiImpl::messages(&mut vm, &maybe_prompt);
// after
if vm.as_instance(&maybe_prompt).is_err() {
return; // receiver is not an ai.Prompt instance
}
let msgs = PackageAiImpl::messages(&mut vm, &maybe_prompt); Defensive patterns
Strategy: type-guard
Validate before calling
fn is_prompt_instance(vm: &BexVm, value: &Value) -> bool {
vm.as_instance(value).is_ok()
} Type guard
fn prompt_receiver<'a>(vm: &BexVm, v: &'a Value) -> Option<&'a Instance> {
vm.as_instance(v).ok()
} Try / catch
// Guard the receiver before the method call:
if prompt_receiver(&vm, &value).is_none() { return; /* not an ai.Prompt */ } Prevention
- Invoke Prompt methods via normal BAML method-call syntax so the receiver binds automatically.
- In embeddings, check as_instance before dispatching class methods.
- Don't pass primitives or maps where an ai.Prompt receiver is expected.
When it happens
Trigger: Calling `ai.Prompt.messages` with a value that is not a class instance (a primitive, a map, a union value) — typically from custom glue code, reflection-based dispatch, or a dispatch bug that fails to bind the receiver.
Common situations: Embedding the VM and invoking Prompt methods manually with wrong receiver values; partially applied/curried native calls where the receiver argument was dropped.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- ai.Prompt._data must contain baml_builtins2::PromptAst
- sys_op callee must resolve to a statically-known global func
- expected jump instruction at index {instruction_idx}
- exhaustive realized-leaf template classification
- ntypeargs fits u16
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e1190ca5ba929617.
Report an issue: GitHub.