kopia/kopia · error

cannot create temporary file

Error message

cannot create temporary file

What it means

createTempFileWithData calls createTempFileAndDir to create a uniquely named '<path>.tmp.<hex>' file (creating intermediate directories as needed); this error wraps any failure to create it, such as permission errors or filesystem exhaustion. The temp-file approach ensures atomic puts via later rename.

Solutions

  1. Read the wrapped OS error (EACCES/ENOSPC/EMFILE etc.) and address it specifically
  2. Verify the storage directory is writable by the running user (ls -ld, try touch)
  3. Free disk space / inodes if the error indicates exhaustion (df -h, df -i)
  4. Raise the open-file limit (ulimit -n) if EMFILE, and check for fd leaks

Example fix

// before (read-only mount)
mount -o ro /mnt/storage
// after
mount -o rw /mnt/storage && chown app:app /mnt/storage/dir
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Dir(targetPath)
if info, err := os.Stat(dir); err != nil || !info.IsDir() { return fmt.Errorf("storage dir missing: %s", dir) }
if err := os.WriteFile(filepath.Join(dir, ".write-test"), nil, 0o600); err != nil { return fmt.Errorf("storage dir not writable: %w", err) }
os.Remove(filepath.Join(dir, ".write-test"))

Try / catch

err := st.PutBlob(ctx, blobID, data, blob.PutOptions{})
if err != nil && strings.Contains(err.Error(), "cannot create temporary file") {
    var perr *fs.PathError
    if errors.As(err, &perr) {
        switch perr.Err {
        case syscall.ENOSPC: freeDiskSpace()
        case syscall.EMFILE: raiseFdLimit()
        case syscall.EACCES: fixPermissions(perr.Path)
        }
    }
    return err
}

Prevention

When it happens

Trigger: PutBlob/PutBlobInPath where creating the temp file fails: read-only filesystem, missing write permission in the target directory, disk full, too many open files, or inability to create missing parent directories.

Common situations: Read-only container filesystems; disk-quota or inode exhaustion; wrong ownership on the storage directory; SELinux/AppArmor denying writes; EMFILE after fd leaks.

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


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/2723fb0eea9e79f0. Report an issue: GitHub.

Appendix: source

Thrown at repo/blob/filesystem/filesystem_storage.go:227

	}), fs.isRetriable)

	return err
}

// createTempFileWithData creates a temporary file, writes data to it, syncs and closes it.
// Returns the name of the temporary file and an error.
// If there is an error writing, syncing, or closing the file, the temporary file is removed.
func (fs *fsImpl) createTempFileWithData(path string, data blob.Bytes) (name string, err error) {
	randSuffix := make([]byte, tempFileRandomSuffixLen)
	if _, err := rand.Read(randSuffix); err != nil {
		return "", errors.Wrap(err, "can't get random bytes for temporary filename")
	}

	tempFile := fmt.Sprintf("%s.tmp.%x", path, randSuffix)

	f, err := fs.createTempFileAndDir(tempFile)
	if err != nil {
		return "", errors.Wrap(err, "cannot create temporary file")
	}

	defer func() {
		if closeErr := f.Close(); closeErr != nil {
			err = stderrors.Join(err, errors.Wrap(closeErr, "can't close temporary file"))
		}

		// remove temp file when any of the operations fail
		if err != nil {
			name = ""

			if removeErr := fs.osi.Remove(tempFile); removeErr != nil {
				err = stderrors.Join(err, errors.Wrap(removeErr, "can't remove temp file after error"))
			}
		}
	}()

	if _, err = data.WriteTo(f); err != nil {

View on GitHub (pinned to 82495e54b5)