BoundaryML/baml · error

unexpected type for client name: %T

Error message

unexpected type for client name: %T

What it means

LLMCall.ClientName() asserts that the value returned by the runtime for "client_name" is a Go string. This error is thrown when the raw FFI result deserializes to a different Go type (%T prints the actual type), meaning the runtime sent an unexpected payload shape for the attribute. It indicates a Go-binding/runtime contract mismatch rather than anything the caller did wrong.

Source

Thrown at engine/language_client_go/pkg/rawobjects_llm_call.go:44

func (l *llmCall) RequestId() (string, error) {
	result, err := raw_objects.CallMethod(l, "http_request_id", nil)
	if err != nil {
		return "", fmt.Errorf("failed to get request id: %w", err)
	}

	return result.(string), nil
}

func (l *llmCall) ClientName() (string, error) {
	result, err := raw_objects.CallMethod(l, "client_name", nil)
	if err != nil {
		return "", fmt.Errorf("failed to get client name: %w", err)
	}

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

	return name, nil
}

func (l *llmCall) Provider() (string, error) {
	result, err := raw_objects.CallMethod(l, "provider", nil)
	if err != nil {
		return "", fmt.Errorf("failed to get provider: %w", err)
	}

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

	return provider, nil
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Align Go binding and BAML CLI/runtime versions (go get github.com/boundaryml/baml@latest and regenerate) so the expected wire types match.
  2. Check the %T value in the message to identify what the runtime actually returned, and report/compare against the binding's expected type.
  3. Log the error defensively and fall back to the event payload's client name instead of crashing on the raw accessor.
  4. If reproducible, file a bug with BoundaryML including the %T value and both versions.

Example fix

// before
name, err := llmCall.ClientName()
if err != nil { panic(err) }

// after
name, err := llmCall.ClientName()
if err != nil {
    log.Printf("client name type mismatch (%v); skipping", err)
    name = "unknown"
}
Defensive patterns

Strategy: fallback

Type guard

func safeClientName(call baml.LLMCall) string {
    name, err := call.ClientName()
    if err != nil {
        return "unknown"
    }
    return name
}

Try / catch

name, err := call.ClientName()
if err != nil {
    var s string
    _ = s
    log.Printf("client name type mismatch: %v", err)
    name = "unknown"
}

Prevention

When it happens

Trigger: raw_objects.CallMethod(l, "client_name", nil) succeeds but returns a non-string (e.g. a raw CFFI wrapper, []byte, or nil interface) that fails the result.(string) type assertion at rawobjects_llm_call.go:42-45.

Common situations: Mismatched versions of the Go bindings and the native BAML runtime where "client_name" is encoded differently; a runtime bug or schema change that changed the attribute's type; passing through an object whose client_name was never a string internally.

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