{"record":{"id":"abe0423cf7caea67","repo":"siyuan-note/siyuan","slug":"failed-to-export-headers-w","errorCode":null,"errorMessage":"failed to export headers: %w","messagePattern":"failed to export headers: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_client.go","lineNumber":75,"sourceCode":"\n\t\tif goja.IsString(call.Argument(0)) {\n\t\t\tpath = call.Argument(0).String()\n\t\t} else {\n\t\t\targErr = fmt.Errorf(\"path required\")\n\t\t}\n\t\tif argErr == nil && !strings.HasPrefix(path, \"/\") {\n\t\t\targErr = fmt.Errorf(\"path must start with /\")\n\t\t}\n\t\tif argErr == nil {\n\t\t\tif init := call.Argument(1); isJsValueNotNull(init) {\n\t\t\t\tif initObj := init.ToObject(rt); initObj != nil {\n\t\t\t\t\tif m := initObj.Get(\"method\"); goja.IsString(m) {\n\t\t\t\t\t\tmethod = m.String()\n\t\t\t\t\t}\n\n\t\t\t\t\tif h := initObj.Get(\"headers\"); isJsValueNotNull(h) {\n\t\t\t\t\t\tif exportErr := rt.ExportTo(h, &headers); exportErr != nil {\n\t\t\t\t\t\t\targErr = fmt.Errorf(\"failed to export headers: %w\", exportErr)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif argErr == nil {\n\t\t\t\t\t\tif b := initObj.Get(\"body\"); isJsValueNotNull(b) {\n\t\t\t\t\t\t\tif goja.IsString(b) {\n\t\t\t\t\t\t\t\tbodyString = new(b.String())\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbody := b.Export()\n\t\t\t\t\t\t\t\tif arrayBuffer, ok := body.(goja.ArrayBuffer); ok {\n\t\t\t\t\t\t\t\t\tsrc := arrayBuffer.Bytes()\n\t\t\t\t\t\t\t\t\tbodyBytes = new(src)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/api_client.go#L57-L93","documentation":"When init.headers is provided to siyuan.client.fetch, the bridge uses rt.ExportTo to convert the JS headers value into a Go http.Header. If the JS value cannot be exported into that Go type, this error rejects the fetch promise. Headers must be a plain object of string keys to (string or string[]) values.","triggerScenarios":"Passing headers as a Headers instance, an array of [k,v] tuples, a Map, a function, or a string instead of a plain object; header values that are numbers/objects which Go cannot decode into http.Header.","commonSituations":"Reusing a browser Headers object built elsewhere; copying axios-style header arrays; passing numeric values like { \"Content-Length\": 123 }.","solutions":["Pass a plain object: { \"Authorization\": \"token xxx\", \"Content-Type\": \"application/json\" }","Convert a Headers instance: Object.fromEntries(headers.entries())","Convert a Map: Object.fromEntries(map)","Ensure all values are strings (or arrays of strings) and header names are strings"],"exampleFix":"// before\nconst h = new Headers({ \"Authorization\": \"token xx\" });\nawait siyuan.client.fetch(\"/api/x\", { headers: h })\n\n// after\nawait siyuan.client.fetch(\"/api/x\", { headers: { \"Authorization\": \"token xx\" } })","handlingStrategy":"type-guard","validationCode":"function validateHeaders(h) {\n  if (h === undefined) return true;\n  if (typeof h !== \"object\" || h === null || Array.isArray(h)) return false;\n  return Object.entries(h).every(([k, v]) =>\n    typeof k === \"string\" && (typeof v === \"string\" || (Array.isArray(v) && v.every((x) => typeof x === \"string\"))));\n}","typeGuard":"const isPlainHeaderObject = (v) => v !== null && typeof v === \"object\" && !Array.isArray(v) && !(v instanceof Headers) && !(v instanceof Map);","tryCatchPattern":"try {\n  const res = await siyuan.client.fetch(path, { headers });\n} catch (e) {\n  if (String(e).includes(\"failed to export headers\")) {\n    headers = Object.fromEntries(\n      headers instanceof Headers ? headers.entries() : Object.entries(headers).map(([k, v]) => [k, String(v)])\n    );\n  }\n}","preventionTips":["Pass headers as plain string-keyed objects with string values","Convert Headers/Map instances with Object.fromEntries(...entries())","Stringify numeric or structured header values before passing"],"tags":["plugin","api","fetch","headers"],"backgroundTag":"config-type-mismatch","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"}