{"record":{"id":"430f8777da2f45d8","repo":"Tencent/WeKnora","slug":"failed-to-save-file-w","errorCode":null,"errorMessage":"failed to save file: %w","messagePattern":"failed to save file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/file/local.go","lineNumber":98,"sourceCode":"\t\tlogger.Errorf(ctx, \"Failed to open source file: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to open file: %w\", err)\n\t}\n\tdefer src.Close()\n\n\t// Create destination file for writing\n\tlogger.Info(ctx, \"Creating destination file\")\n\tdst, err := os.Create(filePath)\n\tif err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to create destination file: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to create file: %w\", err)\n\t}\n\tdefer dst.Close()\n\n\t// Copy content from source to destination\n\tlogger.Info(ctx, \"Copying file content\")\n\tif _, err := io.Copy(dst, src); err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to copy file content: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to save file: %w\", err)\n\t}\n\n\tlogger.Infof(ctx, \"File saved successfully: %s\", filePath)\n\t// Return provider:// path format: local://{relative_path}\n\trelPath, _ := filepath.Rel(s.baseDir, filePath)\n\treturn localScheme + filepath.ToSlash(relPath), nil\n}\n\n// GetFile retrieves a file from the local file system by its path\n// Returns a ReadCloser for reading the file content\n// Supports both provider scheme: local://{relative_path} and legacy absolute paths.\n// 路径必须在 baseDir 下，防止路径遍历（如 ../../）\nfunc (s *localFileService) GetFile(ctx context.Context, filePath string) (io.ReadCloser, error) {\n\tlogger.Infof(ctx, \"Getting file: %s\", filePath)\n\n\tcandidate := s.normalizePathForBase(filePath)\n\tresolved, err := secutils.SafePathUnderBase(s.baseDir, candidate)\n\tif err != nil {","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/local.go#L80-L116","documentation":"SaveFile wraps the error from io.Copy(dst, src) when reading the uploaded file and writing it to disk fails mid-transfer. At this point the destination file exists but is incomplete; the service returns the error without cleaning up the partial file. The wrapped error distinguishes read-side from write-side failures.","triggerScenarios":"io.Copy fails because the source multipart temp file disappears mid-read (client abort), the destination disk fills during the copy, a write error occurs on the storage volume, or an I/O timeout on a network-mounted baseDir.","commonSituations":"Large uploads exceeding free disk space; users cancelling uploads; NFS/EBS volume drop; per-user disk quotas hit during the copy.","solutions":["Check disk space and quotas on the storage volume (df -h, quota reports)","Delete the partial destination file before returning so stale partials don't linger","Correlate client-disconnect logs if the wrapped error is a read failure on the source","Add a pre-flight size check against free space for large uploads"],"exampleFix":"// before\nif _, err := io.Copy(dst, src); err != nil {\n\treturn \"\", fmt.Errorf(\"failed to save file: %w\", err)\n}\n// after: clean up the partial file\nif _, err := io.Copy(dst, src); err != nil {\n\tdst.Close()\n\tos.Remove(filePath)\n\treturn \"\", fmt.Errorf(\"failed to save file: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"if st, err := os.Stat(baseDir); err != nil || st.Mode().Perm()&0o200 == 0 {\n\treturn fmt.Errorf(\"storage not writable\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := io.Copy(dst, src); err != nil {\n\tdst.Close()\n\tos.Remove(filePath) // remove partial file\n\treturn fmt.Errorf(\"failed to save file: %w\", err)\n}","preventionTips":["Check free disk space before large uploads and alert on low space","Clean up partial destination files on copy failure","Handle client aborts gracefully; treat source read errors as retryable uploads","Watch I/O errors on network-mounted storage volumes"],"tags":["go","file-io","io","disk"],"backgroundTag":"file-write-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}