gastownhall/beads · error
failed to create temp file: %w
Error message
failed to create temp file: %w
What it means
atomicWriteFile calls os.CreateTemp in the target file's directory to stage content before an atomic rename. This error wraps CreateTemp failure — the directory doesn't exist, isn't writable, or the OS refused temp-file creation.
Source
Thrown at cmd/bd/backup_export.go:100
// atomicWriteFile writes data to a same-directory temp file, fsyncs the
// temp file's own contents, then renames it into place. This avoids a
// truncated/partial file at path if the process crashes mid-write.
//
// Two caveats this does NOT cover, narrowing the "crash-safe" claim rather
// than the implementation (existing callers' behavior is unchanged here):
// - Only the temp file's contents are fsynced, not the parent directory
// entry; a crash between the rename and a subsequent directory fsync
// can still lose the rename itself on some filesystems.
// - os.Rename's atomic-replace guarantee is a POSIX/Unix property; it is
// not guaranteed on Windows. It also does not follow a symlink at
// path — it replaces whatever is there, symlink or not — so a caller
// that must preserve a symlink's target should resolve path with
// filepath.EvalSymlinks first (see cmd/bd/proxied_server.go).
func atomicWriteFile(path string, data []byte) error {
dir := filepath.Dir(path)
tmp, err := os.CreateTemp(dir, ".backup-tmp-*")
if err != nil {
return fmt.Errorf("failed to create temp file: %w", err)
}
tmpPath := tmp.Name()
if _, err := tmp.Write(data); err != nil {
_ = tmp.Close()
_ = os.Remove(tmpPath)
return fmt.Errorf("failed to write temp file: %w", err)
}
if err := tmp.Sync(); err != nil {
_ = tmp.Close()
_ = os.Remove(tmpPath)
return fmt.Errorf("failed to sync temp file: %w", err)
}
if err := tmp.Close(); err != nil {
_ = os.Remove(tmpPath)
return fmt.Errorf("failed to close temp file: %w", err)
}
if err := os.Rename(tmpPath, path); err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Ensure the target directory exists: mkdir -p .beads (atomicWriteFile does not create parent dirs).
- Check write permission on the directory: ls -ld .beads and chmod/chown appropriately.
- Check disk space and inodes: df -h and df -i.
- If on a read-only mount, remount read/write or point BD_DIR at a writable location.
Example fix
// shell mkdir -p .beads && chmod u+w .beads && bd sync
Defensive patterns
Strategy: validation
Validate before calling
dir := ".beads"
info, err := os.Stat(dir)
if err != nil || !info.IsDir() {
os.MkdirAll(dir, 0o755)
}
// probe writability with a real temp create (same mechanism bd uses)
if f, err := os.CreateTemp(dir, ".probe-*"); err == nil { f.Close(); os.Remove(f.Name()) } Type guard
func dirIsWritable(dir string) bool {
f, err := os.CreateTemp(dir, ".probe-*")
if err != nil { return false }
f.Close(); os.Remove(f.Name())
return true
} Try / catch
if err := saveBackupState(dir, state); err != nil {
if strings.Contains(err.Error(), "create temp file") {
if mkErr := os.MkdirAll(dir, 0o755); mkErr == nil {
err = saveBackupState(dir, state) // one retry after ensuring dir
}
}
if err != nil { return err }
} Prevention
- Never delete or replace the .beads directory while bd commands run
- Check df -h and df -i before large operations
- Keep the workspace on a writable mount, not a read-only container layer
- Use consistent user ownership across CI and local runs
When it happens
Trigger: os.CreateTemp(filepath.Dir(path), ".backup-tmp-*") fails: parent directory missing (e.g. .beads/ deleted), read-only filesystem, disk full of inodes, or permission denied on the directory.
Common situations: .beads directory removed while bd ran; running inside a read-only container mount; full disk/inode exhaustion; wrong user without write access to .beads; TMP restrictions on hardened systems.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- ensureProxiedServerConfig: write %s: %w
- identity: write proxy secret: %w
- dolt path is not executable
- failed to create backup directory: %w
- failed to close temp file: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/049cdd2775495652.
Report an issue: GitHub.