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

  1. Convert the value to a supported type (string, number, bool, slice, string-keyed map)
  2. Use the generated BAML client types for classes/enums/unions instead of raw Go structs
  3. Implement the BamlSerializer (Encode/BamlTypeName) interface for custom types
  4. 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

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


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