{"record":{"id":"477fbf6e290499e5","repo":"siyuan-note/siyuan","slug":"decode-h-failed-s","errorCode":null,"errorMessage":"decode [h] failed: %s","messagePattern":"decode \\[h\\] failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/network.go","lineNumber":358,"sourceCode":"\t}\n\tuBytes, decErr := base64.RawURLEncoding.DecodeString(uParam)\n\tif decErr != nil {\n\t\terr = fmt.Errorf(\"decode [u] failed: %s\", decErr.Error())\n\t\treturn\n\t}\n\tparsedURL, err = url.ParseRequestURI(string(uBytes))\n\tif err != nil {\n\t\terr = fmt.Errorf(\"parse [u] failed: %s\", err.Error())\n\t\treturn\n\t}\n\n\th := http.Header{}\n\theaders = &h\n\thParam := c.Query(\"h\")\n\tif hParam != \"\" {\n\t\thBytes, decErr := base64.RawURLEncoding.DecodeString(hParam)\n\t\tif decErr != nil {\n\t\t\terr = fmt.Errorf(\"decode [h] failed: %s\", decErr.Error())\n\t\t\treturn\n\t\t}\n\t\tvar record map[string][]string\n\t\tif jsonErr := json.Unmarshal(hBytes, &record); jsonErr != nil {\n\t\t\terr = fmt.Errorf(\"parse [h] failed: %s\", jsonErr.Error())\n\t\t\treturn\n\t\t}\n\n\t\tfor k, vs := range record {\n\t\t\tfor _, v := range vs {\n\t\t\t\th.Add(k, v)\n\t\t\t}\n\t\t}\n\t}\n\n\ttimeout = 30 * time.Second\n\ttParam := c.Query(\"t\")\n\tif tParam != \"\" {","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/api/network.go#L340-L376","documentation":"The optional `h` query param of the forward-proxy endpoint carries request headers as base64 RawURLEncoding of a JSON object map[string][]string. If base64 decoding of `h` fails, the handler returns \"decode [h] failed: <reason>\".","triggerScenarios":"Supplying `h` that is not valid RawURLEncoding base64: standard base64 with padding or +// characters, mangling by URL encoding, or truncation.","commonSituations":"Custom scripts that JSON-encode headers but use stdEncoding base64; shell quoting stripping characters; hand-copying an encoded value from logs.","solutions":["Encode the headers JSON with base64.RawURLEncoding (no padding, URL-safe alphabet)","Only send `h` when you actually have headers; omit the param entirely otherwise (it is optional)","Round-trip decode the value in your client to confirm correctness before the request"],"exampleFix":"// before\nconst h = btoa(JSON.stringify({\"X-Token\": [\"abc\"]})); // std base64 with padding\n// after\nconst h = btoa(JSON.stringify({\"X-Token\": [\"abc\"]})).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");","handlingStrategy":"validation","validationCode":"const h = headers && Object.keys(headers).length ? toBase64Url(JSON.stringify(headers)) : null;","typeGuard":"function isValidBase64Url(s) {\n  return /^[A-Za-z0-9_-]+$/.test(s);\n}","tryCatchPattern":null,"preventionTips":["Omit the h param entirely when no headers are needed","Use one shared base64url+JSON encoder for header maps"],"tags":["base64","encoding","headers","proxy"],"backgroundTag":"invalid-argument-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}