Tencent/WeKnora · error
failed to open file: %w
Error message
failed to open file: %w
What it means
SaveFile wraps the error from file.Open() (multipart.FileHeader.Open) when the uploaded file handle cannot be opened. This happens after the multipart form was parsed but before any OBS upload, so nothing was written to the bucket.
Source
Thrown at internal/application/service/file/obs.go:164
}
return "obs://"
}
func (s *obsFileService) SaveFile(ctx context.Context,
file *multipart.FileHeader, tenantID uint64, knowledgeID string,
) (string, error) {
ext := filepath.Ext(file.Filename)
var objectKey string
if s.pathPrefix != "" {
objectKey = fmt.Sprintf("%s/%d/%s/%s%s", s.pathPrefix, tenantID, knowledgeID, uuid.New().String(), ext)
} else {
objectKey = fmt.Sprintf("%d/%s/%s%s", tenantID, knowledgeID, uuid.New().String(), ext)
}
src, err := file.Open()
if err != nil {
return "", fmt.Errorf("failed to open file: %w", err)
}
defer src.Close()
contentType := file.Header.Get("Content-Type")
if contentType == "" {
contentType = "application/octet-stream"
}
_, err = s.client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(s.bucketName),
Key: aws.String(objectKey),
Body: src,
ContentLength: aws.Int64(file.Size),
ContentType: aws.String(contentType),
// ACL: "private",
})
if err != nil {
return "", fmt.Errorf("failed to upload file to OBS: %w", err)View on GitHub (pinned to 988cbb0330)
Solutions
- Inspect the wrapped error (%w) — if it is os.ErrNotExist, the multipart temp file vanished; re-upload instead of retrying Open
- Check the server's temp directory exists, is writable, and is not aggressively cleaned during requests
- Ensure the client request completes fully (timeouts, Content-Length) so the multipart part is intact
- Return 4xx/5xx to the client prompting re-upload rather than retrying server-side
Example fix
// before
src, err := file.Open()
if err != nil { return "", fmt.Errorf("failed to open file: %w", err) }
// after
src, err := file.Open()
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return "", fmt.Errorf("upload temp file lost, re-upload required: %w", err)
}
return "", fmt.Errorf("failed to open file: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if file == nil || file.Size == 0 {
return errors.New("empty or missing upload part")
} Try / catch
path, err := svc.SaveFile(ctx, tenantID, kid, fh)
if err != nil {
if errors.Is(err, fs.ErrNotExist) || strings.Contains(err.Error(), "failed to open file") {
http.Error(w, "upload corrupted, please retry", http.StatusBadRequest)
return
}
http.Error(w, "upload failed", http.StatusInternalServerError)
} Prevention
- Do not disable or over-clean the multipart temp directory during request handling
- Set sane client/server upload timeouts so requests complete
- Distinguish open-failures (client re-upload) from upload-failures (server-side retry)
When it happens
Trigger: Calling SaveFile with a *multipart.FileHeader whose underlying reader cannot be opened — typically a temp file that was removed, or a corrupted multipart part in the HTTP request.
Common situations: Server tmp dir cleaned mid-request (systemd-tmpfiles, /tmp cleanup); very large uploads spilling to disk then failing to reopen; request body truncated/timed out before Open.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- failed to open file: %w
- write file content: %w
- write file content: %w
- failed to save file: %w
- failed to open source file: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/7ad7bd05152a16b9.
Report an issue: GitHub.