BoundaryML/baml · error
unexpected type for usage: %T
Error message
unexpected type for usage: %T
What it means
After Collector.Usage() successfully calls the runtime's `usage` method, it asserts the decoded result implements the Usage interface. If the FFI layer returns any other Go type, this error is thrown. The method call itself succeeded, but the returned payload did not match the documented Usage shape — a contract violation between the native runtime and the Go bindings.
Source
Thrown at engine/language_client_go/pkg/rawobjects_collector.go:35
}
func (c *collector) ObjectType() cffi.BamlObjectType {
return cffi.BamlObjectType_OBJECT_COLLECTOR
}
func (c *collector) pointer() int64 {
return c.RawObject.Pointer()
}
func (c *collector) Usage() (Usage, error) {
result, err := raw_objects.CallMethod(c, "usage", nil)
if err != nil {
return nil, fmt.Errorf("failed to get usage: %w", err)
}
usage, ok := result.(Usage)
if !ok {
return nil, fmt.Errorf("unexpected type for usage: %T", result)
}
return usage, nil
}
func (c *collector) Name() (string, error) {
result, err := raw_objects.CallMethod(c, "name", nil)
if err != nil {
return "", fmt.Errorf("failed to get name: %w", err)
}
name, ok := result.(string)
if !ok {
return "", fmt.Errorf("unexpected type for name: %T", result)
}
return name, nil
}View on GitHub (pinned to bd85ce9dee)
Solutions
- Match Go binding and BAML runtime versions exactly; upgrade/reinstall both together.
- Check whether the underlying collector still tracks active calls; a usage object may only exist after at least one tracked call.
- Recreate the collector and retry to rule out corrupt runtime state.
- Report the printed %T type to BAML maintainers if it reproduces on matched versions.
Example fix
// before
usage, err := collector.Usage()
if err != nil { panic(err) }
// after
usage, err := collector.Usage()
if err != nil {
return nil, fmt.Errorf("usage shape unexpected, verify baml version parity: %w", err)
} Defensive patterns
Strategy: type-guard
Validate before calling
// Only call Usage after at least one tracked call:
// if callCount == 0 { return nil, errors.New("no tracked calls yet") } Type guard
func isUsage(result any) bool {
_, ok := result.(Usage)
return ok
} Try / catch
usage, err := collector.Usage()
if err != nil {
if strings.Contains(err.Error(), "unexpected type for usage") {
return nil, fmt.Errorf("usage payload shape violated (check version parity): %w", err)
}
return nil, err
} Prevention
- Pin Go bindings and runtime to the same version
- Ensure at least one LLM call has been tracked before reading usage
- Avoid caching Usage objects across runtime restarts
When it happens
Trigger: Calling collector.Usage() when the runtime returns a non-Usage value: a raw pointer typed as a different object, nil from a degraded runtime response, or a result decoded with the wrong object type tag.
Common situations: Version drift between the Go module and the native BAML runtime changing the usage object's type tag; runtime-side partial failure producing a placeholder object; a collector created by a different runtime instance.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- unexpected type for name: %T
- unexpected type for class property builders: %T
- unexpected type for class property builder: %T
- unexpected type for class property type: %T
- failed to get usage: %w
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/a196186c4402b760.
Report an issue: GitHub.