siyuan-note/siyuan · error

decode [h] failed: %s

Error message

decode [h] failed: %s

What it means

Returned by parseForwardProxyParams (network.go:371) when the optional `h` query parameter is present but cannot be base64-decoded with RawURLEncoding. `h` carries forwarded request headers as base64(RawURLEncoding) of a JSON map[string][]string; a malformed encoding is rejected with HTTP 400 before any header forwarding.

Source

Thrown at kernel/api/network.go:371

	}
	uBytes, decErr := base64.RawURLEncoding.DecodeString(uParam)
	if decErr != nil {
		err = fmt.Errorf("decode [u] failed: %s", decErr.Error())
		return
	}
	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 != "" {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Encode the header JSON with base64 RawURLEncoding (URL-safe, no padding), the same way as `u`.
  2. Build `h` from JSON.stringify({Header: [values]}) then URL-safe base64, stripping padding.
  3. If you have no headers to forward, omit `h` entirely (it is optional).

Example fix

// before
const h = btoa(JSON.stringify({'X-Key':['v']})) // standard base64
// after
const h = btoa(JSON.stringify({'X-Key':['v']})).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'')
Defensive patterns

Strategy: validation

Validate before calling

function encHeaders(h) {
  const json = JSON.stringify(h); // h is map[string][]string shape
  return btoa(json).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'');
}

Prevention

When it happens

Trigger: Sending ?h=<standard-base64>, ?h=<raw-json>, or a corrupted encoding alongside a valid `u`. base64.RawURLEncoding.DecodeString at network.go:369 fails and the error is wrapped at line 371. httpProxy/wsProxy respond HTTP 400.

Common situations: Client used standard base64 (with '+','/','=' instead of URL-safe chars) for `h`. JSON.stringify of the header map was sent directly instead of base64-encoding it. Padding not stripped. Double URL-encoding mangled the alphabet.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/477fbf6e290499e5. Report an issue: GitHub.