siyuan-note/siyuan · error
parse [t] failed
Error message
parse [t] failed: %s
What it means
Error from parseForwardProxyParams in the network forward-proxy endpoint: the [t] query parameter (request timeout) is present but time.ParseDuration cannot parse it, so the caller supplied an invalid duration string instead of something like "30s".
Solutions
- Use a valid Go duration string: "30s", "5s", "1500ms", "2m"
- Include the unit suffix always; a bare number is invalid for ParseDuration
- Omit `t` to use the default 30s timeout
Example fix
// before
fetch("/api/network/forwardProxy?u=" + u + "&t=30") // no unit
// after
fetch("/api/network/forwardProxy?u=" + u + "&t=30s") Defensive patterns
Strategy: validation
Validate before calling
if (timeoutMs != null) {
const t = (timeoutMs / 1000) + "s"; // Go duration string, e.g. "30s"
} Type guard
function isGoDuration(s) {
return /^\d+(\.\d+)?(ns|us|µs|ms|s|m|h)$/.test(s);
} Prevention
- Always include a unit suffix in the t param (s, ms, m)
- Convert milliseconds to seconds client-side before sending
- Omit t to accept the 30s default
When it happens
Trigger: Sending `t` values like "30" (no unit), "30S", "30sec", "0.5", or any non-duration string. Omitting `t` is fine (defaults to 30s).
Common situations: Clients passing milliseconds as a bare integer assuming it means ms; seconds written without the 's' suffix; locale-formatted numbers like "1,5s".
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- AI editor request timeout
- AI editor stream idle timeout
- attribute view rich text style entity was not restored
- cannot parse document
- capability execution was cancelled before it started
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/e00ef312ad47f267.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/api/network.go:378
}
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 = t
}
}
return
}
// forwardResponseHeaders copies src headers into dst with a "Siyuan-Proxy-" prefix on each key.
func forwardResponseHeaders(dst http.Header, src http.Header) {
for k, vs := range src {
for _, v := range vs {
dst.Add("Siyuan-Proxy-"+k, v)
}
}
}
View on GitHub (pinned to 9f775e8a12)