BoundaryML/baml · error

unexpected type for raw LLM response: %T

Error message

unexpected type for raw LLM response: %T

What it means

RawLLMResponse() retrieves the raw LLM response text for a function log via the language runtime bridge (raw_objects.CallMethod). If the bridge call itself fails it wraps that error; if the bridge returns a value that is not a Go string, it rejects it with 'unexpected type for raw LLM response: %T'. This guards the boundary between the host runtime and Go, where the remote object's return type cannot be statically checked.

Source

Thrown at engine/language_client_go/pkg/rawobjects_function_log.go:105

	}

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

	return usage, nil
}

func (f *functionLog) RawLLMResponse() (string, error) {
	result, err := raw_objects.CallMethod(f, "raw_llm_response", nil)
	if err != nil {
		return "", fmt.Errorf("failed to get raw LLM response: %w", err)
	}

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

	return response, nil
}

func (f *functionLog) CallsCount() (int, error) {
	result, err := raw_objects.CallMethod(f, "calls_count", nil)
	if err != nil {
		return 0, fmt.Errorf("failed to get calls count: %w", err)
	}

	count, ok := result.(int)
	if !ok {
		return 0, fmt.Errorf("unexpected type for calls count: %T", result)
	}

	return count, nil
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Inspect the %T in the error message to identify the actual type returned by the bridge
  2. Verify the runtime objects library (raw_objects) and target runtime versions match the Go binding expectations
  3. Check that the function log actually recorded an LLM response before calling RawLLMResponse
  4. If a known wrapper/byte-slice type is returned, add an explicit conversion before the assertion

Example fix

// before
response, ok := result.(string)
if !ok {
    return "", fmt.Errorf("unexpected type for raw LLM response: %T", result)
}
// after
switch v := result.(type) {
case string:
    return v, nil
case []byte:
    return string(v), nil
default:
    return "", fmt.Errorf("unexpected type for raw LLM response: %T", result)
}
Defensive patterns

Strategy: type-guard

Type guard

func asString(v any) (string, bool) {
    s, ok := v.(string)
    return s, ok
}

Try / catch

resp, err := flog.RawLLMResponse()
if err != nil {
    if strings.Contains(err.Error(), "unexpected type for raw LLM response") {
        // fall back to Calls()/SelectedCall() data or skip this log
        return nil, fmt.Errorf("bridge returned non-string response: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling FunctionLog.RawLLMResponse() when the underlying raw object's 'raw_response' method returns a non-string (e.g. nil, []byte, or a wrapper pointer) because the runtime method failed or returned a different type than expected.

Common situations: Runtime bridge version drift between the Go bindings and the target runtime; the LLM response being unset/None in the runtime so the bridge hands back nil; custom runtimes returning wrapped objects instead of plain strings.

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