BoundaryML/baml · error

failed to decode object handle: %w

Error message

failed to decode object handle: %w

What it means

Within a valid InvocationResponseSuccess, the result oneof must contain an Object carrying a raw object handle. If decodeRawObjectImpl fails to decode that object (bad handle bytes, unknown type id, runtime mismatch), the error is wrapped as 'failed to decode object handle' and delivered as the callback result.

Source

Thrown at engine/language_client_go/pkg/callbacks.go:248

		callbackMutex.Lock()
		defer callbackMutex.Unlock()
		deleteCallback(id)
		return
	}

	switch resp := response.GetResponse().(type) {
	case *cffi.InvocationResponse_Error:
		safeSend(callback.channel, ResultCallback{Error: BamlError{Message: resp.Error}})
	case *cffi.InvocationResponse_Success:
		success := resp.Success
		if success == nil {
			safeSend(callback.channel, ResultCallback{Error: fmt.Errorf("nil success in InvocationResponse")})
		} else {
			switch result := success.GetResult().(type) {
			case *cffi.InvocationResponseSuccess_Object:
				decoded, decodeErr := decodeRawObjectImpl(callback.runtime, result.Object)
				if decodeErr != nil {
					safeSend(callback.channel, ResultCallback{Error: fmt.Errorf("failed to decode object handle: %w", decodeErr)})
				} else {
					safeSend(callback.channel, ResultCallback{HasData: true, Data: decoded})
				}
			default:
				safeSend(callback.channel, ResultCallback{Error: fmt.Errorf("unexpected result type in InvocationResponse: %T", success.GetResult())})
			}
		}
	default:
		safeSend(callback.channel, ResultCallback{Error: fmt.Errorf("unexpected response type in InvocationResponse")})
	}

	safeClose(callback.channel)
	callbackMutex.Lock()
	defer callbackMutex.Unlock()
	deleteCallback(id)
}

func create_unique_id(ctx context.Context, onTick OnTickCallbackData) (uint32, chan ResultCallback) {

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Read the wrapped decodeErr to see whether it's an unknown type or malformed handle bytes.
  2. Ensure the callback runtime (callback.runtime) is the same BamlRuntime instance that produced the object.
  3. Align BAML Go binding and native runtime versions.
  4. If using multiple runtimes, keep object handles scoped to the runtime that created them.

Example fix

// before
handle, err := baml.BuildRequestFromC(otherRuntime, req) // object bound to otherRuntime

// after
handle, err := baml.BuildRequestFromC(currentRuntime, req) // use the same runtime instance
Defensive patterns

Strategy: type-guard

Try / catch

res := <-ch
if res.Error != nil {
	if strings.Contains(res.Error.Error(), "failed to decode object handle") {
		return fmt.Errorf("object handle unusable, recreate request with same runtime: %w", res.Error)
	}
	return res.Error
}

Prevention

When it happens

Trigger: build_request_from_c (or similar) returns an InvocationResponseSuccess_Object whose Object payload cannot be decoded by decodeRawObjectImpl in the current runtime — e.g. handle created by a different runtime instance, corrupted bytes, or unsupported object type id.

Common situations: Sharing object handles across multiple BamlRuntime instances, mixing runtime versions, or the native side returning an object type the Go decoder doesn't know.

Understand the failure class

Related errors


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