vxcontrol/pentagi · error
failed to write temporary upload file
Error message
failed to write temporary upload file: %w
What it means
After creating the temp file, SaveUploadedFileToTemp copies the multipart source into it with io.Copy. If the copy fails mid-stream, the partially written temp file is removed (os.Remove) and this error is returned with the underlying cause (client disconnect, disk full, read error on the multipart stream).
Solutions
- Check whether the wrapped error is syscall.EPIPE / 'unexpected EOF' — the client disconnected; treat as benign client-abort and log at info level.
- Free disk space or raise the volume quota for the temp/upload directory.
- Increase reverse-proxy (nginx client_body_timeout / proxy_read_timeout) and body size limits for large uploads.
- Retry the upload client-side on transient network errors; the temp file is cleaned up automatically.
Example fix
// before
tmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, dir)
if err != nil {
return err
}
// after
tmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, dir)
if err != nil {
if errors.Is(err, syscall.EPIPE) || errors.Is(err, io.ErrUnexpectedEOF) {
log.Info().Err(err).Msg("client aborted upload")
return nil
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check rough size before streaming if the request declares Content-Length:
if r.ContentLength > maxAllowedUpload {
http.Error(w, "file too large", http.StatusRequestEntityTooLarge)
return
} Try / catch
tmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, dir)
if err != nil {
if errors.Is(err, syscall.EPIPE) || errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.Canceled) {
log.Info().Err(err).Msg("upload aborted by client") // temp file already cleaned up
return
}
if errors.Is(err, syscall.ENOSPC) {
http.Error(w, "storage full", http.StatusInsufficientStorage)
return
}
http.Error(w, "upload failed", http.StatusInternalServerError)
return
} Prevention
- Enforce max upload size at the proxy and in handler before reading the body.
- Keep generous disk headroom on the temp/upload volume; monitor with alerts.
- Tune nginx/proxy read timeouts to exceed expected upload durations.
- Remember the function removes the partial temp file — never reuse tmpPath after an error.
When it happens
Trigger: io.Copy(dst, src) returns an error during UploadFlowFiles: the HTTP client disconnected mid-upload (broken pipe / context cancel), the disk filled while writing, or reading from the multipart.FileHeader failed.
Common situations: Users canceling large uploads; reverse proxies (nginx) timing out and dropping the connection; small container disk quotas exceeded by a big file; network interruption between proxy and backend.
Related errors
- failed to create temporary upload file
- failed to write temp file
- failed to create temp directory
- failed to create temp file
- blob for resource not found on disk
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/7bb7196ad6837504.
Report an issue: GitHub.
Appendix: source
Thrown at backend/pkg/flowfiles/files.go:333
}
func SaveUploadedFileToTemp(fh *multipart.FileHeader, dir string) (string, error) {
src, err := fh.Open()
if err != nil {
return "", fmt.Errorf("failed to open uploaded file: %w", err)
}
defer src.Close()
dst, err := os.CreateTemp(dir, ".upload-*")
if err != nil {
return "", fmt.Errorf("failed to create temporary upload file: %w", err)
}
tmpPath := dst.Name()
defer dst.Close()
if _, err := io.Copy(dst, src); err != nil {
os.Remove(tmpPath)
return "", fmt.Errorf("failed to write temporary upload file: %w", err)
}
if err := dst.Chmod(0644); err != nil {
os.Remove(tmpPath)
return "", fmt.Errorf("failed to set temporary upload file permissions: %w", err)
}
return tmpPath, nil
}
func IsWithinDir(absPath, dir string) bool {
return strings.HasPrefix(
filepath.Clean(absPath)+string(filepath.Separator),
filepath.Clean(dir)+string(filepath.Separator),
)
}
func ResolvePulledStagedTarget(stagingDir, cacheRelPath string) string {
candidates := []string{View on GitHub (pinned to ea665308ba)