{"record":{"id":"8fe55d69839366b0","repo":"BoundaryML/baml","slug":"rustdata-cannot-be-serialized","errorCode":null,"errorMessage":"RustData cannot be serialized","messagePattern":"RustData cannot be serialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_vm_types/src/types/object.rs","lineNumber":257,"sourceCode":"            Self::Cell(v) => ObjectWire::Cell(v.clone()),\n            Self::String(v) => ObjectWire::String(v.to_string()),\n            Self::Bigint(v) => ObjectWire::Bigint((**v).clone()),\n            Self::Uint8Array(v) => ObjectWire::Uint8Array(v.lock().clone()),\n            Self::Array(v) => ObjectWire::Array(v.element_ty.clone(), v.data.lock().clone()),\n            Self::Map(v) => ObjectWire::Map(\n                v.key_ty.clone(),\n                v.value_ty.clone(),\n                v.to_index_map()\n                    .into_iter()\n                    .map(|(k, v)| (k.to_string(), v))\n                    .collect(),\n            ),\n            Self::Float(v) => ObjectWire::Float(*v),\n            Self::Future(v) => ObjectWire::Future(v.clone()),\n            Self::UnscheduledFuture(v) => ObjectWire::UnscheduledFuture(v.clone()),\n            Self::Type(v) => ObjectWire::Type(Box::new(v.ty.clone())),\n            Self::RustData(_) => {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::InvalidData,\n                    \"RustData cannot be serialized\",\n                ));\n            }\n            Self::HostClosure(_) => {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::InvalidData,\n                    \"HostClosure cannot be serialized\",\n                ));\n            }\n            #[cfg(feature = \"heap_debug\")]\n            Self::Sentinel(_) => {\n                return Err(std::io::Error::new(\n                    std::io::ErrorKind::InvalidData,\n                    \"Sentinel cannot be serialized\",\n                ));\n            }\n        };","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_vm_types/src/types/object.rs#L239-L275","documentation":"`Object::RustData` wraps an opaque host-side Rust value that has no Borsh wire representation, so `Object`'s `BorshSerialize` returns `Err(InvalidData)` with this message when it encounters that variant. Any object pool containing host data cannot be turned into a pack; the library fails fast rather than silently dropping the payload.","triggerScenarios":"Serializing an `Object` (directly or via `Value`/object-pool/pack serialization) whose variant is `Self::RustData(_)` — i.e. a live VM heap that holds an opaque host object.","commonSituations":"Calling a host function that injected a Rust value into the VM, then attempting to snapshot/persist the heap or pack the program while that value is still reachable; including host objects in a module-level constant; running a pack-export tool against a live session heap.","solutions":["Remove `RustData` values from the value graph before serializing (GC/collect or exclude runtime heap regions).","Represent host data as a registered handle/id (e.g. an integer foreign-object id) that survives serialization instead of embedding the Rust value.","If you control the injection site, only pass plain serializable types (strings, arrays, maps, ints) across the host boundary."],"exampleFix":"// before\nvm.call_host(\"db\", RustData::new(my_pool_connection));\nlet pack = PackEnvelope::new(program, vm.heap()); // io::Error: RustData cannot be serialized\n// after: pass an id, keep the Rust value host-side\nlet handle = host_registry.insert(my_pool_connection);\nvm.call_host(\"db\", Value::Int(handle as i64));\nlet pack = PackEnvelope::new(program, vm.heap());","handlingStrategy":"validation","validationCode":"// before serializing an object graph\nfn graph_is_serializable(values: &[Value]) -> bool {\n    values.iter().all(|v| !matches!(\n        v,\n        Value::Object(o) if matches!(&*o.borrow(), Object::RustData(_) | Object::HostClosure(_))\n    ))\n}","typeGuard":"fn is_rust_data(o: &Object) -> bool {\n    matches!(o, Object::RustData(_))\n}","tryCatchPattern":null,"preventionTips":["Only pass plain data (ints, strings, arrays, maps) across the host/VM boundary.","Keep opaque Rust values in a host-side registry and hand the VM an integer handle.","Serialize only the compiled program pool, never the live session heap.","Before export, run a reachability check that flags `RustData` values with the holding variable's name."],"tags":["rust","serialization","borsh","host-boundary"],"backgroundTag":"json-serialization-failed","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}