siyuan-note/siyuan · error
parse [h] failed
Error message
parse [h] failed: %s
What it means
Error from parseForwardProxyParams in the network forward-proxy endpoint: the base64url-decoded [h] query parameter cannot be unmarshaled into a map[string][]string HTTP header record, so the client sent a malformed header encoding for the proxied request.
Solutions
- Serialize headers as a JSON object whose values are string arrays: {"Header": ["value"]}
- Run the object through JSON.stringify (or json.Marshal) before base64-encoding
- Validate the JSON parses into map[string][]string in your client before sending
Example fix
// before
JSON.stringify({"X-Token": "abc"}) // wrong shape, values must be arrays
// after
JSON.stringify({"X-Token": ["abc"]}) Defensive patterns
Strategy: validation
Validate before calling
const record = {};
for (const [k, v] of Object.entries(headers)) {
record[k] = Array.isArray(v) ? v : [v];
}
const h = toBase64Url(JSON.stringify(record)); Type guard
function isHeaderRecord(o) {
return typeof o === "object" && o !== null && Object.values(o).every(v => Array.isArray(v) && v.every(x => typeof x === "string"));
} Prevention
- Normalize header values to string arrays before serializing
- Always JSON.stringify before base64-encoding, never encode raw text
When it happens
Trigger: `h` decodes to text that is not JSON (plain text, single-quoted JSON, a flat map[string]string instead of map[string][]string).
Common situations: Clients serializing headers as {"X-Token":"abc"} instead of {"X-Token":["abc"]}; string-concatenated pseudo-JSON; forgetting JSON.stringify before base64-encoding.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- builtin color must not be null
- builtin style must not be null
- Conf.Language(317)
- createDocTree definition must be a list
- createDocTree document list must not be empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/af9a3a77e8f3f67d.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/api/network.go:363
}
parsedURL, err = url.ParseRequestURI(string(uBytes))
if err != nil {
err = fmt.Errorf("parse [u] failed: %s", err.Error())
return
}
h := http.Header{}
headers = &h
hParam := c.Query("h")
if hParam != "" {
hBytes, decErr := base64.RawURLEncoding.DecodeString(hParam)
if decErr != nil {
err = fmt.Errorf("decode [h] failed: %s", decErr.Error())
return
}
var record map[string][]string
if jsonErr := json.Unmarshal(hBytes, &record); jsonErr != nil {
err = fmt.Errorf("parse [h] failed: %s", jsonErr.Error())
return
}
for k, vs := range record {
for _, v := range vs {
h.Add(k, v)
}
}
}
timeout = 30 * time.Second
tParam := c.Query("t")
if tParam != "" {
if t, parseErr := time.ParseDuration(tParam); parseErr != nil {
err = fmt.Errorf("parse [t] failed: %s", parseErr.Error())
return
} else {
timeout = tView on GitHub (pinned to 9f775e8a12)