larksuite/cli · error

create temp file: %w

Error message

create temp file: %w

What it means

ExclusiveWriteFromReader writes content to a temp file in the target's directory and then links it into place without ever replacing an existing target. This error wraps the failure of vfs.CreateTemp when creating that staging temp file ('.'+base+'.*.tmp' in the target directory). The write never starts; the original target is untouched.

Source

Thrown at internal/vfs/localfileio/atomicwrite.go:60

// Link, which combines both guarantees this call has to make:
//
//   - No-clobber. Link fails with EEXIST instead of replacing an existing
//     target, so the refusal is decided by the commit itself. A preceding
//     existence check cannot do this: another writer may create the file while
//     this one is still copying.
//   - Whole-file visibility. The target name appears only once the content is
//     complete and synced. Writing directly to the final name with O_EXCL would
//     satisfy no-clobber but publish a partial file for the duration of the
//     copy, and a killed process would leave that partial file behind as a
//     phantom target for the next attempt.
//
// Rename cannot serve as the commit step because it replaces an existing target
// unconditionally.
func ExclusiveWriteFromReader(path string, reader io.Reader, perm os.FileMode) (int64, error) {
	dir := filepath.Dir(path)
	tmp, err := vfs.CreateTemp(dir, "."+filepath.Base(path)+".*.tmp")
	if err != nil {
		return 0, fmt.Errorf("create temp file: %w", err)
	}
	tmpName := tmp.Name()

	closed := false
	defer func() {
		if !closed {
			tmp.Close()
		}
		// The temp name is removed either way: on failure it is the partial
		// artifact, on success the link has already published the content.
		vfs.Remove(tmpName)
	}()

	if err := tmp.Chmod(perm); err != nil {
		return 0, err
	}
	copied, err := io.Copy(tmp, reader)
	if err != nil {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Create the parent directory first (e.g. os.MkdirAll(filepath.Dir(path), 0o755) or the vfs equivalent)
  2. Check that the process has write permission on the target directory
  3. Verify the target path is correct and on a mounted, writable filesystem
  4. Inspect the wrapped cause (%w) — e.g. ENOENT vs EACCES — to distinguish missing dir from permissions

Example fix

// before
n, err := ExclusiveWriteFromReader("/cfg/app/missing/file.json", r, 0o600)
// after
if err := os.MkdirAll("/cfg/app/missing", 0o755); err != nil {
    return err
}
n, err := ExclusiveWriteFromReader("/cfg/app/missing/file.json", r, 0o600)
Defensive patterns

Strategy: validation

Validate before calling

func ensureWritableDir(path string) error {
    dir := filepath.Dir(path)
    fi, err := os.Stat(dir)
    if err != nil { return fmt.Errorf("target dir missing: %w", err) }
    if !fi.IsDir() { return fmt.Errorf("%s is not a directory", dir) }
    if err := syscall.Access(dir, syscall.O_RDWR); err != nil { return fmt.Errorf("dir not writable: %w", err) }
    return nil
}
// call before ExclusiveWriteFromReader / SaveExclusive

Type guard

func canStage(path string) bool {
    dir := filepath.Dir(path)
    fi, err := os.Stat(dir)
    return err == nil && fi.IsDir()
}

Try / catch

if _, err := ExclusiveWriteFromReader(path, r, 0o600); err != nil && strings.Contains(err.Error(), "create temp file") {
    if mkErr := os.MkdirAll(filepath.Dir(path), 0o755); mkErr != nil { return mkErr }
    // retry once after creating the directory
}

Prevention

When it happens

Trigger: The target's parent directory does not exist, is not writable, or the path is invalid, causing CreateTemp to fail — raised via ExclusiveWriteFromReader (called by SaveExclusive and tests).

Common situations: Saving to a directory that was deleted or never created; read-only workspace/config directory; permission-changed directory; path pointing at a nonexistent mount; disk-full edge at creation.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/a953389db1883d8d. Report an issue: GitHub.