BoundaryML/baml · error
unsupported type for BAML encoding: %T (Kind: %s)
Error message
unsupported type for BAML encoding: %T (Kind: %s)
What it means
Catch-all rejection in encodeValue: the value's Go kind is not one BAML can encode (not string, int, float, bool, slice/array, or string-keyed map) and it implements no BAML serializer interface. The error names the concrete Go type and reflect kind so the offending field can be located.
Source
Thrown at engine/language_client_go/baml_go/serde/encode.go:190
case reflect.Map:
if rv.Type().Key().Kind() != reflect.String {
return nil, fmt.Errorf("map key type must be string, got %s", rv.Type().Key().Kind())
}
encoded, err := encodeMap(rv)
if err != nil {
return nil, fmt.Errorf("encoding map: %w", err)
}
return &cffi.HostValue{
Value: &cffi.HostValue_MapValue{
MapValue: encoded,
},
}, nil
default:
// Use originalValue's type for the error message as it's more accurate to the input
return nil, fmt.Errorf("unsupported type for BAML encoding: %T (Kind: %s)", originalValue, rv.Kind())
}
}
// --- Encoding helpers for specific types ---
// encodeList now accepts and passes TypeMap
func encodeList(value reflect.Value) (*cffi.HostListValue, error) {
values := make([]*cffi.HostValue, value.Len())
for i := value.Len() - 1; i >= 0; i-- {
elemOffset, err := encodeValue(value.Index(i).Interface()) // Pass typeMap recursively
if err != nil {
return nil, fmt.Errorf("encoding list element %d: %w", i, err)
}
values[i] = elemOffset
}
return &cffi.HostListValue{
Values: values,View on GitHub (pinned to bd85ce9dee)
Solutions
- Convert the value to a supported type (string, number, bool, slice, string-keyed map)
- Use the generated BAML client types for classes/enums/unions instead of raw Go structs
- Implement the BamlSerializer (Encode/BamlTypeName) interface for custom types
- For internal objects like media, use the provided baml types (e.g. types.Image) rather than custom structs
Example fix
// before
type Point struct{ X, Y int }
b.Fn(ctx, Point{1, 2})
// after
b.Fn(ctx, map[string]any{"x": 1, "y": 2}) Defensive patterns
Strategy: type-guard
Validate before calling
func checkEncodable(v any) error { switch v.(type) { case string, int, int64, float64, bool: return nil }; switch reflect.ValueOf(v).Kind() { case reflect.Slice, reflect.Array, reflect.Map: return nil; default: return fmt.Errorf("unsupported: %T", v) } } Type guard
func isBamlSerializable(v any) bool {
_, a := v.(BamlSerializer); _, b := v.(InternalBamlSerializer)
return a || b || isEncodablePrimitiveOrCollection(v)
} Try / catch
if err := b.Fn(ctx, in); err != nil {
if strings.Contains(err.Error(), "unsupported type for BAML encoding") { /* convert or serialize and retry */ }
} Prevention
- Use generated BAML types for classes/enums/unions instead of raw structs
- Convert time.Time and similar to strings before passing
- Implement BamlSerializer for frequently used custom types
- Audit baml call sites for non-primitive arguments
When it happens
Trigger: Passing structs without a BamlSerializer implementation, channels, funcs, complex numbers, pointers-to-structs lacking serializers, or time.Time-like types as baml function arguments or class fields.
Common situations: Passing time.Time directly; nested custom structs in class fields; using interface{} containers holding exotic types; forgetting to use generated baml types for custom classes.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- encoding internal object: %w
- unsupported type: Checked[any] cannot be passed as inputs to
- unsupported type: StreamState[any] cannot be passed as input
- encoding list: %w
- map key type must be string, got %s
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/3e20153cb3b95865.
Report an issue: GitHub.