BoundaryML/baml · error

failed to get logs: %w

Error message

failed to get logs: %w

What it means

Collector.Logs() calls the runtime's `logs` method and wraps any CallMethod failure as "failed to get logs: %w". The real cause is in the wrapped error: an FFI failure, a runtime exception inside `logs`, or an invalid collector object. It means the log list could not be retrieved at all — the subsequent type assertion on the result never ran.

Source

Thrown at engine/language_client_go/pkg/rawobjects_collector.go:58

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
}

func (c *collector) Logs() ([]FunctionLog, error) {
	result, err := raw_objects.CallMethod(c, "logs", nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get logs: %w", err)
	}

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

	functionLogs := make([]FunctionLog, len(logs))
	for i, log := range logs {
		cast, ok := log.(FunctionLog)
		if !ok {
			return nil, fmt.Errorf("unexpected type in logs: %T", log)
		}
		functionLogs[i] = cast
	}

	return functionLogs, nil
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Unwrap the error (errors.Unwrap) to see the underlying failure before changing application code.
  2. Keep collector usage within the lifetime of the BAML runtime; recreate the collector after any runtime restart.
  3. Synchronize concurrent access to the collector (Clear vs Logs) with a mutex.
  4. Retry once to rule out transient FFI failures, then check runtime logs.

Example fix

// before
logs, err := collector.Logs()
// after
logs, err := collector.Logs()
if err != nil {
    return nil, fmt.Errorf("logs unavailable: %w (cause: %v)", err, errors.Unwrap(err))
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard against races: serialize Clear()/Logs() access with a mutex in your code

Type guard

func hasLogs(c baml.Collector) bool { return c != nil }

Try / catch

logs, err := collector.Logs()
if err != nil {
    if strings.Contains(err.Error(), "failed to get logs") {
        time.Sleep(50 * time.Millisecond)
        logs, err = collector.Logs() // one retry for transient FFI issues
    }
    if err != nil {
        return nil, fmt.Errorf("logs unavailable: %w", err)
    }
}

Prevention

When it happens

Trigger: Calling collector.Logs() when the runtime object is invalid/freed, the runtime raises while collecting logs, or the FFI bridge fails before returning a slice.

Common situations: Reading logs after the BAML runtime shut down; using a collector from a different process/runtime instance; races where one goroutine calls Clear() while another calls Logs().

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/653134d4aa62e4d7. Report an issue: GitHub.