BoundaryML/baml · error · CtypesError
Union selected type `{selected}` is not a member of declared
Error message
Union selected type `{selected}` is not a member of declared union `{union}` What it means
CtypesError::UnionSelectedTypeNotMember { selected, union } is raised when an InboundValue claims a union selected type that is not actually one of the declared union's members. The decoder checks the selection against the declared union descriptor and refuses values that name a foreign or renamed variant, protecting against schema skew and malformed payloads.
Source
Thrown at baml_language/crates/bridge_ctypes/src/error.rs:36
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,
#[error("Union selected type `{selected}` is not a member of declared union `{union}`")]
UnionSelectedTypeNotMember { selected: String, union: String },
#[error("Internal error: {0}")]
InternalError(String),
}
View on GitHub (pinned to bd85ce9dee)
Solutions
- Re-align the producer's schema with the bridge: regenerate bindings after any union member change.
- Check the exact member names (the error names `selected` and `union`) and fix the selected value or the descriptor.
- Upgrade both sides to matching versions so the union definition agrees.
- Validate selections against the declared union in the host before the FFI call.
Example fix
// before selected = "Image" # removed from union in new schema send_inbound(union="Media", selected=selected) // after selected = "ImageUrl" # current member of Media send_inbound(union="Media", selected=selected)
Defensive patterns
Strategy: validation
Validate before calling
def ensure_union_member(declared_union: set[str], selected: str):
if selected not in declared_union:
raise ValueError(f"{selected} is not a member of the declared union") Try / catch
try:
val = bridge.decode_inbound(buf, len(buf))
except BridgeError as e:
if "is not a member of declared union" in str(e):
raise ValueError("schema skew: regenerate producer bindings for the union") from e
raise Prevention
- Regenerate bindings on both sides whenever union members change
- Validate selected variant names against the current schema before FFI calls
- Keep producer and bridge on the same version in deployment
When it happens
Trigger: Decoding an inbound value where value_type/selected names a type absent from the declared union's member list — e.g. after renaming or removing a union member, or crossing bridge/library version boundaries.
Common situations: BAML schema updated (member added/renamed/removed) but the producer still sends the old selected-type name; two libraries at different versions disagreeing on union members; typos in hand-built descriptors.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid InboundValue.value_type: a root union or optional do
- Protobuf decode error: {0}
- Map entry missing key
- Failed to decode Value
- failed to decode object response: %w
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/a1c237772c8a56a0.
Report an issue: GitHub.