BoundaryML/baml · error

unexpected type for function name: %T

Error message

unexpected type for function name: %T

What it means

Returned by FunctionName() when the runtime successfully answered the 'function_name' method call, but the decoded Go value is not a string (the `result.(string)` assertion failed). The library guards its FFI contract with this assertion, so hitting it means the runtime returned a differently-typed representation than the Go client expects — usually a version/contract mismatch or object corruption, never a normal user-visible value problem.

Source

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

	}

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

	return id, nil
}

func (f *functionLog) FunctionName() (string, error) {
	result, err := raw_objects.CallMethod(f, "function_name", nil)
	if err != nil {
		return "", fmt.Errorf("failed to get function name: %w", err)
	}

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

	return name, nil
}

func (f *functionLog) LogType() (string, error) {
	result, err := raw_objects.CallMethod(f, "log_type", nil)
	if err != nil {
		return "", fmt.Errorf("failed to get log type: %w", err)
	}

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

	return logType, nil
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Regenerate/re-version the Go client (`baml generate`) so it matches the installed BAML runtime version.
  2. Capture the %T value in the error message — it reveals what type the runtime actually returned and helps diagnose the mismatch.
  3. Avoid holding functionLog references after the owning function stream finished; recreate access from the current response.
  4. If reproducible on a fresh, valid log object, file a bug with BAML including the printed Go type.

Example fix

// before
name, err := fnLog.FunctionName()
// after
name, err := fnLog.FunctionName()
if err != nil {
    var typeErr *fmt.Errorf
    _ = typeErr // inspect message for "unexpected type for function name: %T" and log the dynamic type
    return "", err
}
Defensive patterns

Strategy: type-guard

Validate before calling

if fnLog == nil {
    return errors.New("function log is nil; cannot read FunctionName")
}

Type guard

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

Try / catch

name, err := fnLog.FunctionName()
if err != nil {
    if strings.Contains(err.Error(), "unexpected type for function name:") {
        // capture the dynamic type printed after the colon for diagnosis
        return "", fmt.Errorf("client/runtime contract mismatch: %w", err)
    }
    return "", err
}

Prevention

When it happens

Trigger: function_name on the Rust side decodes into a non-string Go object (e.g. class instance or map) instead of string; mismatched client/runtime versions where the field representation changed.

Common situations: Upgrading the BAML CLI without regenerating the Go client (or vice versa); corrupted/stale functionLog objects reused after stream completion; a bug in decodeObjectResponse producing an unexpected variant.

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