siyuan-note/siyuan · error

missing query param [u]

Error message

missing query param [u]

What it means

Returned by parseForwardProxyParams (network.go:351) when the `u` query parameter is absent or empty. The forward-proxy endpoints (httpProxy, wsProxy) require `u` to carry the base64(RawURLEncoding)-encoded target URL; without it there is no destination to proxy to, so the request is rejected with HTTP 400.

Source

Thrown at kernel/api/network.go:351

	dialer := util.SSRFSafeDialer(timeout)

	client := req.C()
	client.SetTimeout(timeout)
	client.SetDial(dialer.DialContext)
	client.SetRedirectPolicy(req.MaxRedirectPolicy(3))
	return client
}

// parseForwardProxyParams decodes the `u` and `h` query parameters.
//
// Query params:
//   - `u`: RawURLEncoding base64 of the target URL string.
//   - `h`: RawURLEncoding base64 of a JSON object map[string][]string.
//   - `timeout`: The timeout for the request in nanoseconds.
func parseForwardProxyParams(c *gin.Context) (parsedURL *url.URL, headers *http.Header, timeout time.Duration, err error) {
	uParam := c.Query("u")
	if uParam == "" {
		err = fmt.Errorf("missing query param [u]")
		return
	}
	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)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Always include ?u=<base64rawurl(targetURL)> when calling the forward-proxy endpoints.
  2. Build the query with a helper that asserts `u` is non-empty before firing the request.
  3. Check that the target URL string is non-empty before base64-encoding it.

Example fix

// before
fetch(`/api/network/forwardProxy`)
// after
const u = btoa(targetUrl).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'')
fetch(`/api/network/forwardProxy?u=${u}`)
Defensive patterns

Strategy: validation

Validate before calling

// Build the proxy URL with a required non-empty target
function proxyUrl(target) {
  if (!target) throw new Error('target URL required');
  const u = base64UrlSafe(target);
  return `/api/network/forwardProxy?u=${u}`;
}

Try / catch

try { await fetch(proxyUrl(target)); }
catch (e) { if (/missing query param \[u\]/.test(e.msg)) { /* rebuild URL with u param */ } else throw e; }

Prevention

When it happens

Trigger: Calling /api/network/forwardProxy (HTTP) or the WS proxy endpoint without ?u=... in the query string. parseForwardProxyParams at network.go:348 reads c.Query("u") and returns this error at line 351 when it equals "". httpProxy/wsProxy then respond with HTTP 400 (network.go:421, 478).

Common situations: Frontend/proxy client forgot to append the `u` parameter. The base64-encoded URL was computed into a different variable and not added to the request URL. A misrouted request hitting the proxy endpoint without the expected query contract.

Related errors


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