{"record":{"id":"a1a0ac43714cc6f7","repo":"siyuan-note/siyuan","slug":"write-file-failed-s","errorCode":null,"errorMessage":"write file failed: %s","messagePattern":"write file failed: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/httprequest.go","lineNumber":368,"sourceCode":"\tif resp.ContentLength > maxReadBytes {\n\t\treturn statusCode, contentType, \"\", errors.New(\"response too large\")\n\t}\n\n\trespBody, rerr := io.ReadAll(io.LimitReader(resp.Body, maxReadBytes))\n\tif rerr != nil {\n\t\treturn statusCode, contentType, \"\", errors.New(\"read body failed: \" + rerr.Error())\n\t}\n\n\t// 二进制响应落盘，返回文件路径，供智能体按需进一步处理。\n\tif !isTextContentType(contentType) {\n\t\timportDir := filepath.Join(TempDir, \"import\")\n\t\tif merr := os.MkdirAll(importDir, 0755); merr != nil {\n\t\t\treturn statusCode, contentType, \"\", errors.New(\"create import dir failed: \" + merr.Error())\n\t\t}\n\t\tfilename := extractFilename(rawURL, contentType)\n\t\tfilePath := filepath.Join(importDir, filename)\n\t\tif werr := os.WriteFile(filePath, respBody, 0644); werr != nil {\n\t\t\treturn statusCode, contentType, \"\", errors.New(\"write file failed: \" + werr.Error())\n\t\t}\n\t\treturn statusCode, contentType, fmt.Sprintf(\"Saved to: %s (%d bytes)\", filePath, len(respBody)), nil\n\t}\n\n\treturn statusCode, contentType, truncateRunes(string(respBody), maxHTTPRequestChars), nil\n}\n\n// isTextContentType 判断 Content-Type 是否为可直接展示给智能体的文本类响应。\n// 覆盖 text/*、application/json、application/xml、application/*+json 等。\nfunc isTextContentType(contentType string) bool {\n\tct := strings.ToLower(strings.TrimSpace(strings.SplitN(contentType, \";\", 2)[0]))\n\tif ct == \"\" {\n\t\treturn false\n\t}\n\tif strings.HasPrefix(ct, \"text/\") {\n\t\treturn true\n\t}\n\tswitch ct {","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/util/httprequest.go#L350-L386","documentation":"os.WriteFile failed while saving a downloaded binary response to <workspace temp>/import/<filename>; the filename is derived by extractFilename from the URL and content type. The suffix carries the OS error - disk full, permission denied, or (on Windows) a locked existing file. Text responses never hit this path.","triggerScenarios":"Disk fills exactly between the mkdir and the write; the import directory is read-only; an antivirus or indexer holds the target file open on Windows; a same-named file exists with restrictive permissions.","commonSituations":"Repeated large downloads filling the temp volume; leftover files from earlier runs with different ownership; AV interference on Windows.","solutions":["Free disk space on the temp volume and retry the download","Clean stale files out of <workspace temp>/import","Check permissions on the target file/directory and exclude the temp dir from AV real-time scanning on Windows"],"exampleFix":"// before: import dir filled by earlier downloads, disk full\nutil.HTTPRequest(\"GET\", bigFileURL, nil, \"\")\n\n// after: clean stale imports before large downloads\nimportDir := filepath.Join(util.TempDir, \"import\")\nif entries, derr := os.ReadDir(importDir); derr == nil {\n    for _, e := range entries {\n        os.Remove(filepath.Join(importDir, e.Name()))\n    }\n}","handlingStrategy":"try-catch","validationCode":"if probe, perr := os.CreateTemp(filepath.Join(util.TempDir, \"import\"), \"probe-*\"); perr != nil {\n    return perr // disk full or read-only: skip the binary download\n} else {\n    probe.Close()\n    os.Remove(probe.Name())\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"write file failed\") {\n    cleanImportDir() // remove stale files, then retry the download once\n}","preventionTips":["Periodically clean <workspace temp>/import of downloaded files","Keep disk headroom above the 10 MiB binary cap before agent sessions","On Windows, exclude the temp dir from antivirus real-time scanning"],"tags":["filesystem","disk","agent-tools"],"backgroundTag":"file-write-failed","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}