BoundaryML/baml · error

unsupported type for BAML encoding: %T

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.

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.

Appendix: 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)