{"record":{"id":"735030ab9a805993","repo":"BoundaryML/baml","slug":"unexpected-response-type-in-invocationresponse","errorCode":null,"errorMessage":"unexpected response type in InvocationResponse","messagePattern":"unexpected response type in InvocationResponse","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/language_client_go/pkg/callbacks.go","lineNumber":257,"sourceCode":"\tcase *cffi.InvocationResponse_Success:\n\t\tsuccess := resp.Success\n\t\tif success == nil {\n\t\t\tsafeSend(callback.channel, ResultCallback{Error: fmt.Errorf(\"nil success in InvocationResponse\")})\n\t\t} else {\n\t\t\tswitch result := success.GetResult().(type) {\n\t\t\tcase *cffi.InvocationResponseSuccess_Object:\n\t\t\t\tdecoded, decodeErr := decodeRawObjectImpl(callback.runtime, result.Object)\n\t\t\t\tif decodeErr != nil {\n\t\t\t\t\tsafeSend(callback.channel, ResultCallback{Error: fmt.Errorf(\"failed to decode object handle: %w\", decodeErr)})\n\t\t\t\t} else {\n\t\t\t\t\tsafeSend(callback.channel, ResultCallback{HasData: true, Data: decoded})\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tsafeSend(callback.channel, ResultCallback{Error: fmt.Errorf(\"unexpected result type in InvocationResponse: %T\", success.GetResult())})\n\t\t\t}\n\t\t}\n\tdefault:\n\t\tsafeSend(callback.channel, ResultCallback{Error: fmt.Errorf(\"unexpected response type in InvocationResponse\")})\n\t}\n\n\tsafeClose(callback.channel)\n\tcallbackMutex.Lock()\n\tdefer callbackMutex.Unlock()\n\tdeleteCallback(id)\n}\n\nfunc create_unique_id(ctx context.Context, onTick OnTickCallbackData) (uint32, chan ResultCallback) {\n\tid := nextCallbackID.Add(1)\n\tcallbackMutex.Lock()\n\tdefer callbackMutex.Unlock()\n\tdynamicCallbacks[id] = CallbackData{channel: make(chan ResultCallback, 64), ctx: ctx, onTick: onTick, responseType: responseTypeValue}\n\tcallbackLog(\"[CLIENT_GO_CALLBACK_ADD] id=%d map_size=%d\", id, len(dynamicCallbacks))\n\treturn id, dynamicCallbacks[id].channel\n}\n\n// create_unique_id_for_object creates a callback ID for object-handle responses (e.g. build_request).","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_go/pkg/callbacks.go#L239-L275","documentation":"The outer switch on InvocationResponse.GetResponse() expects either an Error or a Success case. Any other (or unset) oneof state falls to the default branch and produces this error, meaning the response message arrived without a valid response variant.","triggerScenarios":"The native side returns an InvocationResponse with neither Error nor Success set — typically a zero-value/empty protobuf response due to an internal failure before response construction, or a protocol version mismatch that drops the oneof field.","commonSituations":"Native runtime crash or early-return path that emits an empty response; mismatched Go bindings vs native library; corrupted callback payload that partially decodes.","solutions":["Upgrade and align BAML Go bindings and native runtime versions.","Check native runtime logs for an internal failure preceding the callback.","Retry the operation once to rule out a transient empty-response race.","Report with versions and a minimal reproduction if persistent."],"exampleFix":"// before\nres := <-callbackCh // Error: unexpected response type in InvocationResponse\n\n// after\nif res.Error != nil {\n    if strings.Contains(res.Error.Error(), \"unexpected response type\") {\n        log.Printf(\"baml protocol error, check version alignment: %v\", res.Error)\n    }\n    return res.Error\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 2; attempt++ {\n\tres := <-ch\n\tif res.Error == nil {\n\t\treturn res.Data, nil\n\t}\n\tif !strings.Contains(res.Error.Error(), \"unexpected response type in InvocationResponse\") || attempt == 1 {\n\t\treturn nil, res.Error\n\t}\n\t// empty/invalid oneof: retry once for transient empty response\n}","preventionTips":["Keep versions aligned between bindings and runtime","Check native runtime logs for precursor internal errors","Add a single retry for empty-response races"],"tags":["go","protobuf","ffi","protocol"],"backgroundTag":"unexpected-response-shape","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}