vxcontrol/pentagi · error

failed to create temporary upload file: %w

Error message

failed to create temporary upload file: %w

What it means

SaveUploadedFileToTemp streams a multipart upload into a temp file created via os.CreateTemp(dir, ".upload-*"). This error wraps the failure of that CreateTemp call, meaning no temp file could be created in the target directory. Since no file was created, nothing needs cleanup — only the wrapped OS error is propagated.

Source

Thrown at backend/pkg/flowfiles/files.go:326

		return nil, err
	}
	if !info.Mode().IsRegular() {
		return nil, fmt.Errorf("'%s' is not a regular file", filePath)
	}

	return info, nil
}

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(

View on GitHub (pinned to ea665308ba)

Solutions

  1. Verify dir exists and is writable by the process user; run os.MkdirAll(dir, 0755) before calling SaveUploadedFileToTemp.
  2. Check disk space (df) and inodes (df -i) on the volume backing dir.
  3. If running in a container, confirm dir is on a writable volume, not a read-only rootfs; add a volume mount for the uploads path.
  4. Fix filesystem ownership/permissions (chown/chmod) for the service account.

Example fix

// before
tmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, cfg.UploadDir)
// after
if err := os.MkdirAll(cfg.UploadDir, 0o755); err != nil {
    return fmt.Errorf("prepare upload dir: %w", err)
}
tmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, cfg.UploadDir)
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(dir)
if err != nil || !info.IsDir() {
    return fmt.Errorf("upload dir %q missing: %w", dir, err)
}
probe, err := os.CreateTemp(dir, ".probe-*")
if err != nil {
    return fmt.Errorf("upload dir %q not writable: %w", dir, err)
}
probe.Close(); os.Remove(probe.Name())

Try / catch

tmpPath, err := flowfiles.SaveUploadedFileToTemp(fh, dir)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) && (errors.Is(pe.Err, syscall.ENOSPC) || errors.Is(pe.Err, syscall.EACCES) || errors.Is(pe.Err, syscall.EROFS)) {
        http.Error(w, "storage temporarily unavailable", http.StatusServiceUnavailable)
        return
    }
    http.Error(w, "upload failed", http.StatusInternalServerError)
    return
}

Prevention

When it happens

Trigger: Calling SaveUploadedFileToTemp(fh, dir) when: dir does not exist, the process lacks write permission on dir, dir points to a read-only filesystem (e.g. container rootfs), or the filesystem is full / inode-exhausted so CreateTemp's random-name retries all fail.

Common situations: Docker containers with read-only or tiny tmpfs mount points; the uploads directory deleted after image build; running as non-root user without ownership of the temp dir; disk-full on busy hosts after many uploads.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/789ac955c01fb382. Report an issue: GitHub.