{"record":{"id":"42e1f9b2a75edd5d","repo":"siyuan-note/siyuan","slug":"write-file-failed-s-42e1f9","errorCode":null,"errorMessage":"write file failed: %s","messagePattern":"write file failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/webfetch.go","lineNumber":85,"sourceCode":"\t}\n\tif resp.ContentLength > maxReadBytes {\n\t\treturn \"\", errors.New(\"response too large\")\n\t}\n\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, maxReadBytes))\n\tif err != nil {\n\t\treturn \"\", errors.New(\"read body failed: \" + err.Error())\n\t}\n\n\tif !strings.HasPrefix(contentType, \"text/html\") && !strings.HasPrefix(contentType, \"text/plain\") {\n\t\timportDir := filepath.Join(TempDir, \"import\")\n\t\tif merr := os.MkdirAll(importDir, 0755); merr != nil {\n\t\t\treturn \"\", 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, body, 0644); werr != nil {\n\t\t\treturn \"\", errors.New(\"write file failed: \" + werr.Error())\n\t\t}\n\t\treturn fmt.Sprintf(\"Saved to: %s (%d bytes)\", filePath, len(body)), nil\n\t}\n\n\thtmlStr := string(body)\n\n\tisHTML := strings.HasPrefix(contentType, \"text/html\")\n\tif !isHTML {\n\t\treturn truncateRunes(htmlStr, maxWebFetchChars), nil\n\t}\n\n\tif htmlStr == \"\" {\n\t\treturn \"\", nil\n\t}\n\n\tengine := NewLute()\n\tvar result string\n\tswitch format {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/webfetch.go#L67-L103","documentation":"After creating the import directory, WebFetch writes the downloaded bytes with os.WriteFile(filePath, body, 0644); any write failure (permission denied, disk full, invalid filename path) is wrapped as 'write file failed: <cause>'. The download itself succeeded; persisting it failed.","triggerScenarios":"The temp volume is full or read-only; the extractFilename-derived name resolves to a path that cannot be created; an antivirus or OS policy blocks writing the file type; permission changed between mkdir and write.","commonSituations":"Disk quota exceeded on the workspace volume; fetching files whose derived names are unusually long (exceeding filesystem NAME_MAX on some systems); SELinux/AppArmor denials in hardened deployments.","solutions":["Read the wrapped cause after 'write file failed: ' (ENOSPC vs EACCES vs ENAMETOOLONG)","Free disk space or raise the quota on the temp/workspace volume","Verify the kernel process can create files in <TempDir>/import (test with touch)","Shorten or sanitize the source URL so extractFilename produces a shorter filename"],"exampleFix":"// before\n// ENOSPC: disk full, silent until this error\n$ df -h /tmp   # check free space\n\n// after\n$ df -h /tmp && du -sh <workspace>/*   # identify and clear space, then retry","handlingStrategy":"try-catch","validationCode":"importDir := filepath.Join(TempDir, \"import\")\nif f, err := os.CreateTemp(importDir, \"probe-*\"); err != nil {\n    return errors.New(\"temp import dir not writable: \" + err.Error())\n} else {\n    f.Close(); os.Remove(f.Name())\n}","typeGuard":null,"tryCatchPattern":"_, err := WebFetch(url, format)\nif err != nil && strings.Contains(err.Error(), \"write file failed\") {\n    // check ENOSPC (free space/quota), EACCES (permissions), ENAMETOOLONG (shorten URL)\n}","preventionTips":["Monitor free space and inode/quota limits on the temp volume","Keep source URLs reasonably short — extractFilename derives the saved name from them","Verify write access to <TempDir>/import after user or deployment changes","Account for security software that may block writes of downloaded file types"],"tags":["filesystem","write","disk"],"backgroundTag":"file-write-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}