siyuan-note/siyuan · error
write file failed: %s
Error message
write file failed: %s
What it means
Raised by HTTPRequest after the import directory is created but os.WriteFile cannot persist the binary response body to TempDir/import/<filename>. The %s is the wrapped OS write error. The filename comes from extractFilename(rawURL, contentType), which derives it from the URL path or a random string plus a content-type extension.
Source
Thrown at kernel/util/httprequest.go:121
if resp.ContentLength > maxReadBytes {
return statusCode, contentType, "", errors.New("response too large")
}
respBody, rerr := io.ReadAll(io.LimitReader(resp.Body, maxReadBytes))
if rerr != nil {
return statusCode, contentType, "", errors.New("read body failed: " + rerr.Error())
}
// 二进制响应落盘,返回文件路径,供智能体按需进一步处理。
if !isTextContentType(contentType) {
importDir := filepath.Join(TempDir, "import")
if merr := os.MkdirAll(importDir, 0755); merr != nil {
return statusCode, contentType, "", errors.New("create import dir failed: " + merr.Error())
}
filename := extractFilename(rawURL, contentType)
filePath := filepath.Join(importDir, filename)
if werr := os.WriteFile(filePath, respBody, 0644); werr != nil {
return statusCode, contentType, "", errors.New("write file failed: " + werr.Error())
}
return statusCode, contentType, fmt.Sprintf("Saved to: %s (%d bytes)", filePath, len(respBody)), nil
}
return statusCode, contentType, truncateRunes(string(respBody), maxHTTPRequestChars), nil
}
// sendByMethod 按 method 分发请求,统一走 NewBrowserRequest 返回的 *req.Request。
func sendByMethod(request *req.Request, method, rawURL string) (*req.Response, error) {
switch method {
case "GET", "":
return request.Get(rawURL)
case "POST":
return request.Post(rawURL)
case "PUT":
return request.Put(rawURL)
case "DELETE":
return request.Delete(rawURL)View on GitHub (pinned to 251596fc0d)
Solutions
- Check free space on the TempDir volume (df) and free space or raise maxHTTPRequestFileBytes awareness before large downloads.
- Inspect the resolved filename in the error path for illegal characters and sanitize the URL or set a Content-Disposition-friendly name upstream.
- Ensure no other process (sync client, AV) holds an exclusive lock on TempDir/import.
- Retry the http_request; transient write failures (lock, momentary full disk) often clear.
Example fix
// before: large binary write fails on full disk
// after: preflight free space before calling HTTPRequest for big assets
var stat syscall.Statfs_t
if err := syscall.Statfs(util.TempDir, &stat); err == nil {
free := stat.Bavail * uint64(stat.Bsize)
if free < uint64(maxHTTPRequestFileBytes) {
return errors.New("insufficient disk space for binary download")
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight free-space check for binary downloads.
var stat syscall.Statfs_t
if err := syscall.Statfs(filepath.Join(util.TempDir, "import"), &stat); err == nil {
free := stat.Bavail * uint64(stat.Bsize)
if free < 10*1024*1024 {
return errors.New("insufficient disk space for binary download")
}
} Try / catch
statusCode, contentType, text, err := util.HTTPRequest(method, rawURL, headers, body)
if err != nil && strings.Contains(err.Error(), "write file failed") {
// transient: disk full / lock; surface to caller, suggest retry after cleanup
return fmt.Errorf("binary save failed (free space / lock?): %w", err)
} Prevention
- Monitor free space on the TempDir volume.
- Sanitize URL path segments before they become filenames.
- Avoid concurrent http_request calls that resolve to the same filename.
When it happens
Trigger: A non-text response is written with os.WriteFile(filePath, respBody, 0644) and the write fails. Causes: destination volume is full, the resolved filename contains characters the filesystem rejects, the path is too long, or the directory was removed between MkdirAll and WriteFile (TOCTOU).
Common situations: Disk full when the agent downloads a large binary (up to maxHTTPRequestFileBytes = 10 MiB); a URL whose final path segment contains illegal filename characters on the host OS; antivirus or sync software locking the import directory; concurrent http_request calls racing on the same filename.
Related errors
- create import dir failed: %s
- unsupported method: %s
- url is required for http server
- save OAuth client registration: %w
- save OAuth credentials: %w
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/a1a0ac43714cc6f7.
Report an issue: GitHub.