{"record":{"id":"ba91b44b76d6a98d","repo":"router-for-me/CLIProxyAPI","slug":"plugin-call-s-returned-d-s","errorCode":null,"errorMessage":"plugin call %s returned %d: %s","messagePattern":"plugin call (.+?) returned (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/loader_unix.go","lineNumber":197,"sourceCode":"\tvar cRequest unsafe.Pointer\n\tif len(request) > 0 {\n\t\tcRequest = C.CBytes(request)\n\t\tdefer C.free(cRequest)\n\t}\n\tvar response C.cliproxy_buffer\n\trc := C.cliproxy_call_plugin(c.api.call, cMethod, (*C.uint8_t)(cRequest), C.size_t(len(request)), &response)\n\tvar out []byte\n\tif response.ptr != nil && response.len > 0 {\n\t\tout = C.GoBytes(response.ptr, C.int(response.len))\n\t}\n\tif response.ptr != nil {\n\t\tC.cliproxy_free_plugin_buffer(c.api.free_buffer, response.ptr, response.len)\n\t}\n\tif rc != 0 {\n\t\tif isPluginErrorEnvelope(out) {\n\t\t\treturn out, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"plugin call %s returned %d: %s\", method, int(rc), string(out))\n\t}\n\treturn out, nil\n}\n\nfunc (c *dynamicLibraryClient) Shutdown() {\n\tif c == nil {\n\t\treturn\n\t}\n\tif c.api.shutdown != nil {\n\t\tC.cliproxy_shutdown_plugin(c.api.shutdown)\n\t\tc.api.shutdown = nil\n\t}\n\tif c.hostCtx != nil {\n\t\tid := uintptr(*(*C.uintptr_t)(c.hostCtx))\n\t\thostCallbackEntries.Delete(id)\n\t\tC.free(c.hostCtx)\n\t\tc.hostCtx = nil\n\t}","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/loader_unix.go#L179-L215","documentation":"The native plugin entry point (invoked via cgo cliproxy_call_plugin) returned a nonzero return code, and the response body was not a recognized plugin error envelope. The message embeds the RPC method name, the numeric rc, and whatever bytes the plugin wrote to the response buffer. This is the generic failure path for unix dynamic-library plugins.","triggerScenarios":"Plugin method implementation returns an error without serializing it as a plugin error envelope; calling a method name the plugin does not implement; plugin crashes or corrupts its own state inside call(); ABI drift where the plugin misinterprets arguments.","commonSituations":"Plugin built against an older SDK version that formats errors differently; method name typo in the host-side dispatch (e.g. camelCase vs snake_case); plugin panicking across the C boundary and returning garbage; plugin out-of-memory returning rc != 0 with empty output.","solutions":["Check the plugin's own logs/stderr for the real cause; the %s payload usually carries the plugin's error text","Verify the method name string matches exactly what the plugin registers","Rebuild the plugin against the same pluginhost SDK/ABI version as the host binary","If you author the plugin, return errors as the SDK's error envelope so the host surfaces them as structured responses instead of this opaque failure"],"exampleFix":"// before\nresp, err := client.Call(ctx, \"transform.Request\", body)\nif err != nil { log.Fatal(err) }\n\n// after\nresp, err := client.Call(ctx, \"transform.Request\", body)\nif err != nil {\n    log.Errorf(\"plugin rpc failed (method=%s): %v\", \"transform.Request\", err)\n    return fallbackResponse // degrade gracefully instead of crashing\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"out, err := client.Call(ctx, method, body)\nif err != nil {\n    log.WithError(err).WithField(\"method\", method).Error(\"plugin rpc failed\")\n    return nil, err // or serve degraded response","preventionTips":["Pin plugin builds to the same SDK commit as the host","Log the method name with every plugin call so the %s in this error maps to a code path","In plugin code, always serialize errors via the SDK error envelope"],"tags":["plugin","cgo","rpc","dynamic-library"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}