BoundaryML/baml · error · CtypesError
Protobuf decode error: {0}
Error message
Protobuf decode error: {0} What it means
CtypesError::ProtobufDecode wraps a prost::DecodeError raised while decoding a protobuf-encoded message crossing the bridge FFI boundary. It means the byte buffer handed to the ctypes conversion layer was not valid protobuf for the expected message type (corrupt, truncated, or produced by an incompatible schema).
Source
Thrown at baml_language/crates/bridge_ctypes/src/error.rs:8
//! Error types used by the shared ctypes conversion logic.
use thiserror::Error;
/// Errors that can occur during value encoding/decoding for the bridge.
#[derive(Debug, Error)]
pub enum CtypesError {
#[error("Protobuf decode error: {0}")]
ProtobufDecode(#[from] prost::DecodeError),
#[error("Null buffer pointer")]
NullBuffer,
#[error("Invalid handle key: {0}")]
InvalidHandleKey(u64),
#[error("Map entry missing key")]
MapEntryMissingKey,
/// Carries only the input length, not the input itself — untrusted hex
/// blobs can be up to the FFI decode cap (~67M chars), and embedding
/// them in error messages bloats logs and exposes payload contents.
#[error("Invalid bigint hex string ({len} bytes)")]
InvalidBigint { len: usize },
/// Carries only the input length for over-cap decimal type literals, so aView on GitHub (pinned to bd85ce9dee)
Solutions
- Ensure the caller encodes with the same protobuf schema version the bridge was built with; rebuild/realign both sides.
- Verify the buffer length and contents before the call (decode the bytes independently with prost to see the underlying error).
- Check that the full serialized message, not a truncated slice, is passed.
- Regenerate the protobuf bindings if the schema was updated.
Example fix
// before let val = bridge::decode_inbound(&buf[..len-1])?; // truncated -> ProtobufDecode // after let val = bridge::decode_inbound(&buf)?;
Defensive patterns
Strategy: validation
Validate before calling
import google.protobuf # Independently decode before crossing the FFI boundary: msg.ParseFromString(buf) # raises DecodeError early with a clear cause assert msg.IsInitialized()
Try / catch
try:
result = bridge.decode(buf, len(buf))
except BridgeError as e:
if "Protobuf decode error" in str(e):
raise ValueError(f"payload not valid protobuf (len={len(buf)})") from e
raise Prevention
- Pin and regenerate protobuf bindings on both sides of the FFI when the schema changes
- Always pass the full serialized buffer with its exact length
- Unit-test the encode->decode round trip whenever you touch serialization
When it happens
Trigger: Calling bridge functions that accept encoded InboundValue/descriptor buffers when the bytes fail prost decoding — wrong message type, truncated buffer, mismatched protobuf schema versions between host and library.
Common situations: Version skew between a client SDK and the native bridge library (schema changed); buffers truncated to an FFI length cap; passing raw (non-protobuf) bytes; endianness/copy bugs in the caller's marshalling code.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- Failed to decode Value
- Map entry missing key
- Invalid InboundValue.value_type: a root union or optional do
- Key is missing
- Value is null for key {}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/f37002a7e948ccbb.
Report an issue: GitHub.