plandex-ai/plandex · error

error writing file: %v

Error message

error writing file: %v

What it means

After the directory exists, the goroutine writes the original file body (context.Body) into the temp repo with os.WriteFile. A failure here (permissions, ENOSPC, invalid path, temp dir removed) is sent on errCh and later wrapped by GetPlanDiffs as 'error writing original files to temp dir: error writing file: ...'.

Source

Thrown at app/server/db/diff_helpers.go:72

					log.Printf("panic in GetPlanDiffs: %v\n%s", r, debug.Stack())
					errCh <- fmt.Errorf("panic in GetPlanDiffs: %v\n%s", r, debug.Stack())
					runtime.Goexit() // don't allow outer function to continue and double-send to channel
				}
			}()
			_, hasPath := files[path]
			_, hasRemoved := removed[path]
			if hasPath || hasRemoved {
				hasAnyOriginal = true
				// ensure file directory exists
				err = os.MkdirAll(filepath.Dir(filepath.Join(tempDirPath, path)), 0755)
				if err != nil {
					errCh <- fmt.Errorf("error creating directory: %v", err)
					return
				}

				err = os.WriteFile(filepath.Join(tempDirPath, path), []byte(context.Body), 0644)
				if err != nil {
					errCh <- fmt.Errorf("error writing file: %v", err)
					return
				}
			}
			errCh <- nil
		}(path, context)
	}

	for range planState.ContextsByPath {
		err = <-errCh
		if err != nil {
			return "", fmt.Errorf("error writing original files to temp dir: %v", err)
		}
	}

	if hasAnyOriginal {
		// add and commit the files in the temp dir
		err := gitAdd(tempDirPath, ".")
		if err != nil {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Read the wrapped os error to identify ENOSPC/EACCES/ENAMETOOLONG and address that specific cause.
  2. Free disk space or increase quota for the org/tmp volume.
  3. Verify temp dir exists and is writable for the whole GetPlanDiffs run; stop concurrent cleanup jobs.
  4. Validate/sanitize the file path before writing (no NUL, no '..').

Example fix

// before
err = os.WriteFile(filepath.Join(tempDirPath, path), []byte(context.Body), 0644)
// after
if err := os.WriteFile(filepath.Join(tempDirPath, path), []byte(context.Body), 0644); err != nil {
    errCh <- fmt.Errorf("error writing file %s: %v", path, err)
    return
}
Defensive patterns

Strategy: validation

Validate before calling

if len(context.Body) > maxFileBodyBytes {
    return fmt.Errorf("file body for %s exceeds %d bytes", path, maxFileBodyBytes)
}
if err := hasFreeSpace(tempDirPath, uint64(len(context.Body))); err != nil {
    return err
}

Try / catch

out, err := GetPlanDiffs(orgId, planId, plain)
var pathErr *os.PathError
if err != nil && errors.As(err, &pathErr) {
    log.Printf("filesystem failure on %s: %v", pathErr.Path, pathErr.Err)
    // ENOSPC -> free space; EACCES -> fix permissions
}

Prevention

When it happens

Trigger: os.WriteFile(filepath.Join(tempDirPath, path), []byte(context.Body), 0644) fails: disk full, permissions, path too long, or temp dir deleted mid-run.

Common situations: Very large file bodies exceeding quota/disk; read-only mounts; tmp cleaner racing the goroutines; filenames from plan state that the local filesystem cannot represent.

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 plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/d1d7b4cfe2483947. Report an issue: GitHub.