siyuan-note/siyuan · error

parse [u] failed

Error message

parse [u] failed: %s

What it means

After successfully decoding the `u` param, parseForwardProxyParams validates it with url.ParseRequestURI. If the decoded string is not a parseable absolute request URI, the error is "parse [u] failed: <reason>". This means base64 was fine but the payload was not a usable URL.

Solutions

  1. Ensure the pre-encoding string is a full absolute URL including scheme, e.g. https://host/path
  2. Trim whitespace and remove control characters from the URL before encoding
  3. Percent-encode non-ASCII characters in path/query before base64-encoding
  4. Validate with url.ParseRequestURI in your client before sending

Example fix

// before
const target = "example.com/api"; // no scheme -> parse [u] failed
// after
const target = "https://example.com/api";
Defensive patterns

Strategy: validation

Validate before calling

try { new URL(targetUrl); } catch { throw new Error("Target must be an absolute http(s) URL"); }
if (!/^https?:\/\//.test(targetUrl)) throw new Error("Target URL must include scheme");

Type guard

function isAbsoluteHttpUrl(s) {
  try { const u = new URL(s); return u.protocol === "http:" || u.protocol === "https:"; } catch { return false; }
}

Prevention

When it happens

Trigger: Decoded `u` value that is empty, relative (e.g. "foo/bar"), contains spaces or control characters, or lacks a scheme/host form acceptable to ParseRequestURI.

Common situations: Encoding the wrong variable (a path instead of a full URL); a client that strips the scheme; URLs containing unencoded whitespace or non-ASCII characters.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/bbfa86966202c9ad. Report an issue: GitHub.

Appendix: source

Thrown at kernel/api/network.go:348

//
// 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)
		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
		}

View on GitHub (pinned to 9f775e8a12)