{"record":{"id":"cf7db20e9057b48f","repo":"router-for-me/CLIProxyAPI","slug":"decode-host-auth-save-request-w","errorCode":null,"errorMessage":"decode host auth save request: %w","messagePattern":"decode host auth save request: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/auth_callbacks.go","lineNumber":119,"sourceCode":"\tauthIndex := strings.TrimSpace(req.AuthIndex)\n\tif authIndex == \"\" {\n\t\treturn nil, fmt.Errorf(\"auth_index is required\")\n\t}\n\tauth, errGet := h.authByIndex(authIndex)\n\tif errGet != nil {\n\t\treturn nil, errGet\n\t}\n\tentry := h.buildHostAuthFileEntry(auth)\n\tif entry == nil {\n\t\treturn nil, fmt.Errorf(\"auth runtime info not found for auth_index %s\", authIndex)\n\t}\n\treturn marshalRPCResult(pluginapi.HostAuthGetRuntimeResponse{Auth: *entry})\n}\n\nfunc (h *Host) callHostAuthSave(ctx context.Context, request []byte) ([]byte, error) {\n\tvar req pluginapi.HostAuthSaveRequest\n\tif errUnmarshal := json.Unmarshal(request, &req); errUnmarshal != nil {\n\t\treturn nil, fmt.Errorf(\"decode host auth save request: %w\", errUnmarshal)\n\t}\n\tname, rawJSON, errValidate := validateHostAuthSaveRequest(req)\n\tif errValidate != nil {\n\t\treturn nil, errValidate\n\t}\n\tpath, errSave := h.saveAuthFile(ctx, name, rawJSON)\n\tif errSave != nil {\n\t\treturn nil, errSave\n\t}\n\treturn marshalRPCResult(pluginapi.HostAuthSaveResponse{\n\t\tName: name,\n\t\tPath: path,\n\t})\n}\n\nfunc (h *Host) listAuthFiles() ([]pluginapi.HostAuthFileEntry, error) {\n\tmanager := h.currentAuthManager()\n\tif manager != nil {","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/auth_callbacks.go#L101-L137","documentation":"The host's auth.save RPC callback could not decode its request into pluginapi.HostAuthSaveRequest — invalid JSON or wrong field types. Saving is rejected before validateHostAuthSaveRequest even runs.","triggerScenarios":"Plugin calls host auth save with a malformed payload — non-JSON bytes, wrong types for Name/JSON fields, or a truncated frame; also mismatched pluginapi struct definitions between plugin and host versions.","commonSituations":"Plugin serializing the auth JSON by string concatenation producing invalid JSON; plugin/host version skew after upgrading one side only; transport framing bug splitting the payload.","solutions":["Log and JSON-validate the exact payload the plugin sends for save","Build the request with the pluginapi types (json.Marshal of a HostAuthSaveRequest) rather than manual strings","Upgrade plugin and host together so both sides share the same pluginapi definitions","Verify transport framing (length prefixes) if payloads arrive truncated"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Plugin side: marshal structured types and pre-validate the JSON blob.\nraw, err := json.Marshal(authData)\nif err != nil { return err }\nreq := pluginapi.HostAuthSaveRequest{Name: name, JSON: raw}\nif !json.Valid(req.JSON) { return errors.New(\"auth payload not valid JSON\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never build auth JSON by string concatenation; use json.Marshal","Validate writes with json.Valid before sending","Upgrade plugin and host together; save payload shapes change across pluginapi versions"],"tags":["plugin","rpc","json","validation","auth-save"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}