siyuan-note/siyuan · error · Error
data?.msg || data?.message || window.siyuan.languages._kerne
Error message
data?.msg || data?.message || window.siyuan.languages._kernel[28]
What it means
Thrown by util.WebFetch in kernel/util/webfetch.go when the URL parses successfully and carries an http/https scheme, but its host component is empty. This happens with malformed inputs such as "http:///path", "https:/single-slash", or "http://?q=1", which net/url.Parse accepts but which leave u.Host empty. The check exists because an empty host would otherwise send a request to the local machine, which is both useless and an SSRF risk.
Source
Thrown at app/src/ai/editorSSE.ts:110
onEvent: (event: TAIEditorSSEEvent) => void,
signal: AbortSignal,
) => {
const response = await fetch("/api/ai/editor/chat", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(request),
signal,
});
const contentType = response.headers.get("Content-Type") || "";
if (!response.ok || !contentType.includes("text/event-stream")) {
let message = window.siyuan.languages._kernel[28];
try {
const data = await response.json();
message = data?.msg || data?.message || message;
} catch (e) {
// 响应不是 JSON 时使用统一错误文案。
}
throw new Error(message);
}
const reader = response.body?.getReader();
if (!reader) {
throw new Error(window.siyuan.languages._kernel[28]);
}
const decoder = new TextDecoder();
const parserState = createAIEditorSSEParserState();
let terminalReceived = false;
while (true) {
const result = await reader.read();
if (result.done) {
break;
}
parseAIEditorSSE(parserState, decoder.decode(result.value, {stream: true})).forEach(event => {
terminalReceived = terminalReceived || event.type === "done" || event.type === "error";
onEvent(event);
});
}View on GitHub (pinned to afa823b6b4)
Solutions
- Inspect the exact rawURL string passed to WebFetch; look for single-slash schemes ("https:/...") or a missing host segment
- Normalize the URL before calling WebFetch: run url.Parse, require u.Hostname() != "", and repair common typos such as "https:/" -> "https://"
- If the URL comes from an LLM or user input, validate it at the boundary and reject/repair empty-host URLs before it reaches the kernel
- Check for stray whitespace or embedded control characters pasted into the URL
Example fix
// before
result, err := util.WebFetch(userURL, "markdown")
// after
u, perr := url.Parse(strings.TrimSpace(userURL))
if perr != nil || u.Host == "" || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("invalid URL %q: must be a fully-qualified http(s) URL with a host", userURL)
}
result, err := util.WebFetch(u.String(), "markdown") Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(strings.TrimSpace(rawURL))
if err != nil || (u.Scheme != "http" && u.Scheme != "https") || u.Host == "" {
return fmt.Errorf("reject URL %q before WebFetch: need http(s) scheme and non-empty host", rawURL)
}
result, err := util.WebFetch(u.String(), format) Type guard
func isFetchableURL(rawURL string) bool {
u, err := url.Parse(strings.TrimSpace(rawURL))
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
} Try / catch
null
Prevention
- Never build URLs by bare string concatenation; always assemble with url.URL and set u.Host explicitly
- Validate LLM- or user-supplied URLs at the input boundary with url.Parse plus a non-empty Host check
- Trim whitespace and reject control characters before passing URLs to WebFetch
When it happens
Trigger: Calling util.WebFetch(rawURL, format) with a scheme-relative or single-slash URL like "https:/example.com/a" (parses with empty Host), "http:///foo", or a URL built by string concatenation where the host segment was accidentally dropped or contained unescaped characters that broke host parsing.
Common situations: Agent/AI features or plugins passing user-typed or LLM-generated URLs that were truncated or copy-pasted with a missing slash; URLs assembled via fmt.Sprintf where the host variable was empty; input like "https://" passed straight through from a chat prompt.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- URL must start with http:// or https://
- URL value is missing
- URL must start with http:// or https://
- URL has no host
- unrecognized skill source: %s
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/a246c0ac69d48cf3.
Report an issue: GitHub.