BoundaryML/baml · error · CtypesError

Map entry missing key

Error message

Map entry missing key

What it means

CtypesError::MapEntryMissingKey is raised during protobuf value decoding when a map entry arrives without its key field populated. The bridge requires both key and value in each map entry to reconstruct the map.

Source

Thrown at baml_language/crates/bridge_ctypes/src/error.rs:17

//! 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 },

    #[error(
        "Invalid InboundValue.value_type: a root union or optional does not identify one exact selected type"
    )]
    InvalidInboundValueTypeRootUnion,

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Regenerate/upgrade the producer so map entries always set the key field.
  2. Inspect the serialized bytes (decode independently) to find the entry missing its key.
  3. Fix producers that skip empty keys when assembling the map message.
  4. Validate payloads with a round-trip encode/decode before crossing the FFI boundary.

Example fix

// before
entries.push(MapEntry { value: Some(v), ..Default::default() })  // key omitted
// after
entries.push(MapEntry { key: k, value: Some(v), ..Default::default() })
Defensive patterns

Strategy: validation

Validate before calling

for entry in map_value.entries:
    if not entry.HasField("key") or entry.key == "":
        raise ValueError("map entry missing key before FFI decode")

Try / catch

try:
    val = bridge.decode_inbound(buf, len(buf))
except BridgeError as e:
    if "Map entry missing key" in str(e):
        raise ValueError("producer sent a map entry without a key; fix serializer") from e
    raise

Prevention

When it happens

Trigger: Decoding an InboundValue containing a map whose entries have a value but no key — usually a hand-built protobuf message or a schema mismatch where the key field was omitted or serialized as empty.

Common situations: Manually constructed protobuf payloads in tests/tools; older SDK versions serializing maps differently than the bridge expects; a producer bug dropping empty-string keys.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/8b9b1fce8454db2d. Report an issue: GitHub.