{"record":{"id":"b9886e7e6fd235fe","repo":"gastownhall/beads","slug":"atomicfile-create-temp-w","errorCode":null,"errorMessage":"atomicfile: create temp: %w","messagePattern":"atomicfile: create temp: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/atomicfile/atomicfile.go","lineNumber":51,"sourceCode":"// atomically renames it to the target path on Close. Call Abort to\n// discard the temp file without touching the target.\ntype Writer struct {\n\ttarget string\n\tf      *os.File\n\tperm   os.FileMode\n\tdone   bool\n}\n\n// Create returns a Writer that will atomically replace path on Close.\n// The temp file is created in the same directory as path to guarantee\n// same-filesystem rename semantics.\nfunc Create(path string, perm os.FileMode) (*Writer, error) {\n\tdir := filepath.Dir(path)\n\tbase := filepath.Base(path)\n\n\tf, err := os.CreateTemp(dir, \".~\"+base+\".\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"atomicfile: create temp: %w\", err)\n\t}\n\n\treturn &Writer{\n\t\ttarget: path,\n\t\tf:      f,\n\t\tperm:   perm,\n\t}, nil\n}\n\n// Write delegates to the underlying temp file.\nfunc (w *Writer) Write(p []byte) (int, error) {\n\treturn w.f.Write(p)\n}\n\n// Close fsyncs the temp file and atomically renames it to the target path.\n// After Close returns successfully, the target contains exactly the data\n// written. On error the temp file is removed and the target is untouched.\nfunc (w *Writer) Close() error {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/atomicfile/atomicfile.go#L33-L69","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Create the parent directory first (os.MkdirAll(filepath.Dir(path), 0700))","Check directory permissions and that you're running as a user with write access","Verify free disk space / quota on the target filesystem"],"exampleFix":"// before\nw, err := atomicfile.Create(\"/repo/.beads/issues.jsonl\", 0644)\n// after\nos.MkdirAll(\"/repo/.beads\", 0700)\nw, err := atomicfile.Create(\"/repo/.beads/issues.jsonl\", 0644)","handlingStrategy":"validation","validationCode":"if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {\n    return err\n}\nif info, err := os.Stat(filepath.Dir(path)); err != nil || !info.IsDir() {\n    return fmt.Errorf(\"%s is not a writable directory\", filepath.Dir(path))\n}","typeGuard":null,"tryCatchPattern":"w, err := atomicfile.Create(path, 0644)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"atomicfile: create temp\") {\n        return fmt.Errorf(\"cannot write %s: check dir exists and is writable: %w\", path, err)\n    }\n    return err\n}\ndefer func() { if w != nil { w.Abort() } }()","preventionTips":["Always MkdirAll the parent directory before atomic writes","Check disk space/quota in automation that writes many files","Avoid writing to read-only mounts; probe writability at startup"],"tags":["filesystem","io","atomic-write"],"backgroundTag":"temp-file-creation-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}