Tencent/WeKnora · error
failed to save file: %w
Error message
failed to save file: %w
What it means
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.
Source
Thrown at internal/application/service/file/local.go:98
logger.Errorf(ctx, "Failed to open source file: %v", err)
return "", fmt.Errorf("failed to open file: %w", err)
}
defer src.Close()
// Create destination file for writing
logger.Info(ctx, "Creating destination file")
dst, err := os.Create(filePath)
if err != nil {
logger.Errorf(ctx, "Failed to create destination file: %v", err)
return "", fmt.Errorf("failed to create file: %w", err)
}
defer dst.Close()
// Copy content from source to destination
logger.Info(ctx, "Copying file content")
if _, err := io.Copy(dst, src); err != nil {
logger.Errorf(ctx, "Failed to copy file content: %v", err)
return "", fmt.Errorf("failed to save file: %w", err)
}
logger.Infof(ctx, "File saved successfully: %s", filePath)
// Return provider:// path format: local://{relative_path}
relPath, _ := filepath.Rel(s.baseDir, filePath)
return localScheme + filepath.ToSlash(relPath), nil
}
// GetFile retrieves a file from the local file system by its path
// Returns a ReadCloser for reading the file content
// Supports both provider scheme: local://{relative_path} and legacy absolute paths.
// 路径必须在 baseDir 下,防止路径遍历(如 ../../)
func (s *localFileService) GetFile(ctx context.Context, filePath string) (io.ReadCloser, error) {
logger.Infof(ctx, "Getting file: %s", filePath)
candidate := s.normalizePathForBase(filePath)
resolved, err := secutils.SafePathUnderBase(s.baseDir, candidate)
if err != nil {View on GitHub (pinned to 988cbb0330)
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
Example fix
// before
if _, err := io.Copy(dst, src); err != nil {
return "", fmt.Errorf("failed to save file: %w", err)
}
// after: clean up the partial file
if _, err := io.Copy(dst, src); err != nil {
dst.Close()
os.Remove(filePath)
return "", fmt.Errorf("failed to save file: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if st, err := os.Stat(baseDir); err != nil || st.Mode().Perm()&0o200 == 0 {
return fmt.Errorf("storage not writable")
} Try / catch
if _, err := io.Copy(dst, src); err != nil {
dst.Close()
os.Remove(filePath) // remove partial file
return fmt.Errorf("failed to save file: %w", err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Large uploads exceeding free disk space; users cancelling uploads; NFS/EBS volume drop; per-user disk quotas hit during the copy.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- failed to open file: %w
- failed to create file: %w
- failed to delete file: %w
- read response body: %w
- read poll response body: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/430f8777da2f45d8.
Report an issue: GitHub.