BoundaryML/baml · error

unexpected type for headers: %T

Error message

unexpected type for headers: %T

What it means

httpRequest.Headers() expects the runtime 'headers' method to yield a Go map[string]string. 'unexpected type for headers: %T' means the bridge returned a different type — commonly map[string][]string (multi-value headers) or nil.

Source

Thrown at engine/language_client_go/pkg/rawobjects_http_request.go:77

	}

	method, ok := result.(string)
	if !ok {
		return "", fmt.Errorf("unexpected type for method: %T", result)
	}

	return method, nil
}

func (h *httpRequest) Headers() (map[string]string, error) {
	result, err := raw_objects.CallMethod(h, "headers", nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get headers: %w", err)
	}

	headers, ok := result.(map[string]string)
	if !ok {
		return nil, fmt.Errorf("unexpected type for headers: %T", result)
	}

	return headers, nil
}

func (h *httpRequest) Body() (HTTPBody, error) {
	result, err := raw_objects.CallMethod(h, "body", nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get body: %w", err)
	}

	body, ok := result.(HTTPBody)
	if !ok {
		return nil, fmt.Errorf("unexpected type for body: %T", result)
	}

	return body, nil
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Check %T in the message; if it is map[string][]string, adapt at the boundary before this API or convert
  2. Fix the runtime to flatten header values to strings
  3. Treat nil headers as an empty map on the caller side
  4. Align client and runtime versions

Example fix

// before
headers, err := req.Headers()
if err != nil { return err }
// after
if h, ok := rawHeaders.(map[string][]string); ok {
    flat := map[string]string{}
    for k, vs := range h { if len(vs) > 0 { flat[k] = vs[0] } }
    headers = flat
}
Defensive patterns

Strategy: type-guard

Validate before calling

hs, err := req.Headers()
if err == nil && hs == nil { hs = map[string]string{} }

Type guard

func asStringMap(v any) (map[string]string, bool) {
    switch t := v.(type) {
    case map[string]string:
        return t, true
    case map[string][]string:
        m := map[string]string{}
        for k, vs := range t { if len(vs) > 0 { m[k] = vs[0] } }
        return m, true
    }
    return nil, false
}

Try / catch

hs, err := req.Headers()
if err != nil {
    if strings.Contains(err.Error(), "unexpected type") {
        return fmt.Errorf("header representation changed: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: The runtime stores headers as multi-value maps, objects with non-string values (numbers/arrays), or returns nil when no headers exist.

Common situations: Runtime representing headers as map[string]interface{}; headers containing repeated keys or non-string values (Content-Length numbers); cross-version representation changes.

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/fd6c457ae4e171e3. Report an issue: GitHub.