BoundaryML/baml · error · CtypesError
Null buffer pointer
Error message
Null buffer pointer
What it means
CtypesError::NullBuffer is thrown when an FFI conversion function receives a null pointer where a byte buffer was required. The bridge refuses to dereference null and reports this error instead of crashing.
Source
Thrown at baml_language/crates/bridge_ctypes/src/error.rs:11
//! 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 a
/// hostile descriptor cannot amplify logs by echoing its full payload.
#[error("Invalid decimal bigint literal ({len} bytes)")]
InvalidBigintLiteral { len: usize },View on GitHub (pinned to bd85ce9dee)
Solutions
- Check the pointer is non-null before calling the bridge; for empty payloads pass a valid (possibly empty) buffer with len 0.
- In Python, convert None/empty values explicitly to b"" and pass from a real bytes object.
- Audit the FFI shim struct so the buffer field is always initialized.
- Add an assertion/log at the call site to catch the null origin.
Example fix
// before ptr = None lib.decode_inbound(ptr, 0) # NullBuffer // after buf = b"" if data is None else data ptr = (ctypes.c_char * len(buf)).from_buffer_copy(buf) lib.decode_inbound(ptr, len(buf))
Defensive patterns
Strategy: validation
Validate before calling
buf = b"" if data is None else bytes(data)
if ptr is None and len(buf) > 0:
raise ValueError("buffer pointer is null") Try / catch
try:
out = bridge.decode_inbound(ptr, length)
except BridgeError as e:
if "Null buffer pointer" in str(e):
out = bridge.decode_inbound(empty_buf, 0) # or surface a clear host-side error
else:
raise Prevention
- In Python ctypes, always build pointers from real bytes objects, never None
- Initialize all fields of FFI shim structs
- Treat empty payloads as len=0 with a valid (non-null) buffer
When it happens
Trigger: Passing NULL (0) as the data pointer/len pair into bridge encode/decode entry points — e.g. an empty Python bytes converted to a null ctypes pointer, or a failed allocation upstream left the pointer null.
Common situations: ctypes interop in Python where an empty/None value became a null pointer; callers skipping the length=0 shortcut and passing null; uninitialized struct fields in the FFI shim.
Related errors
- Engine not initialized. Call create_baml_runtime first.
- Project not initialized
- unsupported handle type
- {0}
- Protobuf decode error: {0}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/908a482bbed28c24.
Report an issue: GitHub.