{"record":{"id":"83850b7167f50e95","repo":"router-for-me/CLIProxyAPI","slug":"decode-plugin-result-s-w","errorCode":null,"errorMessage":"decode plugin result %s: %w","messagePattern":"decode plugin result (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/rpc_client.go","lineNumber":168,"sourceCode":"\tvar zero T\n\trawRequest, errMarshal := json.Marshal(sanitizePluginRequest(request))\n\tif errMarshal != nil {\n\t\treturn zero, fmt.Errorf(\"marshal plugin request %s: %w\", method, errMarshal)\n\t}\n\trawResp, errCall := client.Call(ctx, method, rawRequest)\n\tif errCall != nil {\n\t\treturn zero, errCall\n\t}\n\tvar envelope pluginabi.Envelope\n\tif errUnmarshal := json.Unmarshal(rawResp, &envelope); errUnmarshal != nil {\n\t\treturn zero, fmt.Errorf(\"decode plugin envelope %s: %w\", method, errUnmarshal)\n\t}\n\tout, errDecode := decodeEnvelopeResult[T](envelope)\n\tif errDecode != nil {\n\t\tif !envelope.OK {\n\t\t\treturn zero, errDecode\n\t\t}\n\t\treturn zero, fmt.Errorf(\"decode plugin result %s: %w\", method, errDecode)\n\t}\n\treturn out, nil\n}\n\nfunc sanitizePluginRequest(request any) any {\n\tswitch req := request.(type) {\n\tcase pluginapi.AuthLoginStartRequest:\n\t\treq.HTTPClient = nil\n\t\treturn req\n\tcase pluginapi.AuthLoginPollRequest:\n\t\treq.HTTPClient = nil\n\t\treturn req\n\tcase pluginapi.AuthRefreshRequest:\n\t\treq.HTTPClient = nil\n\t\treturn req\n\tcase pluginapi.AuthModelRequest:\n\t\treq.HTTPClient = nil\n\t\treturn req","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/rpc_client.go#L150-L186","documentation":"The plugin's reply decoded as a valid envelope with ok=true, but the result payload failed to unmarshal into the concrete Go type T expected by callPlugin (decode plugin result %s). The plugin and host disagree on the shape of the result — wrong field types, renamed fields, or a payload that is not the expected structure.","triggerScenarios":"Host calls e.g. Translate/Execute expecting ExecutorResult while the plugin (different version) returns a changed schema; plugin returns a JSON array where host expects an object; numeric/string field type mismatch.","commonSituations":"Plugin compiled against an older pluginabi/pluginapi with different struct tags; host upgraded without rebuilding third-party plugins; plugin returns null-shaped or empty-object results where a required typed field has an incompatible type.","solutions":["Rebuild/reinstall the plugin against the same CLIProxyAPI version as the host","Inspect the raw envelope.Result for the failing method to see which field mismatches","Pin host and plugin to a compatible release pair until both are upgraded together"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"out, err := callPlugin[TypedResult](ctx, client, \"Method\", req)\nif err != nil && strings.Contains(err.Error(), \"decode plugin result\") {\n    return fmt.Errorf(\"plugin/host version mismatch on %q; rebuild plugin against host v%s\", \"Method\", version)\n}","preventionTips":["Version-pin host and plugins together; rebuild plugins on every host upgrade","In integration tests, round-trip every RPC type through json.Marshal/Unmarshal to catch schema drift early"],"tags":["rpc","plugin","json","version-mismatch"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}