vxcontrol/pentagi · error
failed to write temp file: %w
Error message
failed to write temp file: %w
What it means
SaveToTemp streams the reader into the temp file and an MD5 hasher via io.Copy; this error wraps a copy failure. It indicates the upload data could not be fully read or written — a truncated upload, client disconnect, or disk error. The temp file is removed before returning.
Source
Thrown at backend/pkg/resources/resources.go:290
// the temp file. The caller is responsible for removing the temp file on error.
func SaveToTemp(r io.Reader, dir string) (tmpPath string, hash string, size int64, err error) {
if err := os.MkdirAll(dir, 0755); err != nil {
return "", "", 0, fmt.Errorf("failed to create temp directory: %w", err)
}
tmp, err := os.CreateTemp(dir, ".resource-upload-*")
if err != nil {
return "", "", 0, fmt.Errorf("failed to create temp file: %w", err)
}
tmpPath = tmp.Name()
defer tmp.Close()
h := md5.New()
mw := io.MultiWriter(tmp, h)
written, copyErr := io.Copy(mw, r)
if copyErr != nil {
os.Remove(tmpPath)
return "", "", 0, fmt.Errorf("failed to write temp file: %w", copyErr)
}
if err := tmp.Chmod(0644); err != nil {
os.Remove(tmpPath)
return "", "", 0, fmt.Errorf("failed to set temp file permissions: %w", err)
}
return tmpPath, hex.EncodeToString(h.Sum(nil)), written, nil
}
// CommitBlob atomically moves tmpPath to the .blob destination for hash. If
// the blob already exists (race with concurrent upload of identical file) the
// tmp file is removed and no error is returned.
func CommitBlob(dataDir, hash, tmpPath string) error {
if err := validateBlobHash(hash); err != nil {
return err
}
if err := EnsureResourcesDir(dataDir); err != nil {
return errView on GitHub (pinned to ea665308ba)
Solutions
- Check disk space (df -h) and quotas on the temp directory volume
- Increase proxy/server upload timeouts (e.g. nginx client_body_timeout, proxy_read_timeout) for large files
- Retry the upload from the client; the error is transient for network causes
- Wrap the reader with logging to distinguish client-disconnect from disk errors before calling SaveToTemp
Example fix
// before # nginx default 60s read timeout kills big uploads proxy_read_timeout 60s; // after proxy_read_timeout 600s; client_max_body_size 2G;
Defensive patterns
Strategy: try-catch
Validate before calling
func diskHasSpace(dir string, min uint64) error {
var st syscall.Statfs_t
if err := syscall.Statfs(dir, &st); err != nil {
return err
}
avail := st.Bavail * uint64(st.Bsize)
if avail < min {
return fmt.Errorf("only %d bytes free in %s", avail, dir)
}
return nil
} Try / catch
tmpPath, hash, size, err := resources.SaveToTemp(body, dir)
if err != nil {
if strings.Contains(err.Error(), "failed to write temp file") {
if errors.Is(context.Cause(bodyCtx), context.Canceled) {
return nil // client disconnected; nothing to do
}
log.Error("upload copy failed", "err", err) // check disk/proxy timeouts
return http.StatusInsufficientStorage
}
return err
} Prevention
- Size reverse-proxy timeouts (client_body_timeout, proxy_read_timeout) for your largest uploads
- Monitor free disk space and alert before the volume fills
- Detect client disconnects via request context so disconnects aren't mistaken for disk errors
- Enforce a max upload size before streaming to disk
When it happens
Trigger: HTTP request body closed mid-upload (client disconnect/timeout); disk full while writing; underlying reader (network stream, multipart part) returning an I/O error. Raised via UploadResources.
Common situations: Large file uploads exceeding a reverse-proxy body timeout (nginx proxy_read_timeout); user cancels upload in browser; diskquota exceeded on the container volume; flaky network between proxies.
Related errors
- failed to write temporary upload file: %w
- image download stream processing failed: %w
- failed to create temporary upload file: %w
- failed to read response body: %w
- failed to copy output: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/9f93892710dfc57b.
Report an issue: GitHub.