gastownhall/beads · error

atomicfile: create temp: %w

Error message

atomicfile: create temp: %w

What it means

atomicfile.Create writes via a temp file in the target's directory; it first calls os.CreateTemp(dir, ".~"+base+"."). If creating that temp file fails — the directory does not exist, is not writable, or the filesystem rejects the name — the error is wrapped with the 'atomicfile: create temp' prefix.

Source

Thrown at internal/atomicfile/atomicfile.go:51

// atomically renames it to the target path on Close. Call Abort to
// discard the temp file without touching the target.
type Writer struct {
	target string
	f      *os.File
	perm   os.FileMode
	done   bool
}

// Create returns a Writer that will atomically replace path on Close.
// The temp file is created in the same directory as path to guarantee
// same-filesystem rename semantics.
func Create(path string, perm os.FileMode) (*Writer, error) {
	dir := filepath.Dir(path)
	base := filepath.Base(path)

	f, err := os.CreateTemp(dir, ".~"+base+".")
	if err != nil {
		return nil, fmt.Errorf("atomicfile: create temp: %w", err)
	}

	return &Writer{
		target: path,
		f:      f,
		perm:   perm,
	}, nil
}

// Write delegates to the underlying temp file.
func (w *Writer) Write(p []byte) (int, error) {
	return w.f.Write(p)
}

// Close fsyncs the temp file and atomically renames it to the target path.
// After Close returns successfully, the target contains exactly the data
// written. On error the temp file is removed and the target is untouched.
func (w *Writer) Close() error {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Create the parent directory first (os.MkdirAll(filepath.Dir(path), 0700))
  2. Check directory permissions and that you're running as a user with write access
  3. Verify free disk space / quota on the target filesystem

Example fix

// before
w, err := atomicfile.Create("/repo/.beads/issues.jsonl", 0644)
// after
os.MkdirAll("/repo/.beads", 0700)
w, err := atomicfile.Create("/repo/.beads/issues.jsonl", 0644)
Defensive patterns

Strategy: validation

Validate before calling

if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
    return err
}
if info, err := os.Stat(filepath.Dir(path)); err != nil || !info.IsDir() {
    return fmt.Errorf("%s is not a writable directory", filepath.Dir(path))
}

Try / catch

w, err := atomicfile.Create(path, 0644)
if err != nil {
    if strings.HasPrefix(err.Error(), "atomicfile: create temp") {
        return fmt.Errorf("cannot write %s: check dir exists and is writable: %w", path, err)
    }
    return err
}
defer func() { if w != nil { w.Abort() } }()

Prevention

When it happens

Trigger: Calling Create (or WriteFile) with a path whose parent directory does not exist, on a read-only directory or filesystem, or when the process lacks write permission; also on full disks or quota exhaustion.

Common situations: Pointing bd at a path in a non-existent directory, running as a user without write access to ~/.beads or the repo, or exporting to a mounted read-only volume.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/b9886e7e6fd235fe. Report an issue: GitHub.