{"record":{"id":"e85e4571ea9fb1b2","repo":"gastownhall/beads","slug":"failed-to-write-interactions-log-entry-w","errorCode":null,"errorMessage":"failed to write interactions log entry: %w","messagePattern":"failed to write interactions log entry: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/audit/audit.go","lineNumber":151,"sourceCode":"\t}\n\n\tf, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) // nolint:gosec // intended permissions\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to open interactions log: %w\", err)\n\t}\n\tdefer func() { _ = f.Close() }() // Best effort: file close in defer after flush\n\n\t// Marshal to a single byte slice and write atomically.\n\t// Using bufio.NewWriter could split into multiple write() syscalls,\n\t// which interleave under concurrent O_APPEND and corrupt lines.\n\tvar buf bytes.Buffer\n\tenc := json.NewEncoder(&buf)\n\tenc.SetEscapeHTML(false)\n\tif err := enc.Encode(e); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to marshal interactions log entry: %w\", err)\n\t}\n\tif _, err := f.Write(buf.Bytes()); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to write interactions log entry: %w\", err)\n\t}\n\n\treturn e.ID, nil\n}\n\n// AppendIfEnabled appends only when the optional JSONL sidecar is enabled.\nfunc AppendIfEnabled(e *Entry) (string, error) {\n\tif !Enabled() {\n\t\treturn \"\", fmt.Errorf(\"audit JSONL sidecar is disabled; set audit.enabled=true or BD_AUDIT_ENABLED=1 to write %s\", FileName)\n\t}\n\treturn Append(e)\n}\n\n// LogFieldChange logs a field change (status, assignee, priority, etc.) to the\n// optional JSONL sidecar when it is enabled. First-class issue history is\n// recorded separately in the database events tables. Best-effort: errors are\n// silently ignored so sidecar logging never blocks operations.\n// Optional reason is included when non-empty (e.g., close reason, cleanup rule).","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/audit/audit.go#L133-L169","documentation":"Append writes the fully encoded JSON line in a single f.Write call (deliberately avoiding bufio to keep O_APPEND writes atomic), and wraps any write failure as \"failed to write interactions log entry\". This indicates the file was opened successfully but the data could not be written — typically disk full, I/O errors, or the file descriptor going bad. A partial write here can corrupt a JSONL line, so the error is not recoverable within the same call.","triggerScenarios":"Disk quota or filesystem full when appending; EIO from failing hardware or network filesystems (NFS); file removed/unlinked while open in exotic setups; RLIMIT_FSIZE reached.","commonSituations":"CI runners with small ephemeral disks accumulating large audit logs; home directories on full NFS mounts; containers hitting their writable-layer size limit.","solutions":["Free disk space or increase the quota on the volume holding .beads/.","Check the filesystem for errors (dmesg / SMART) if EIO is reported.","Rotate or truncate an oversized interactions.jsonl.","Retry the append once — transient NFS hiccups may clear.","Verify RLIMIT_FSIZE is not limiting the process (ulimit -f)."],"exampleFix":"// before\nif _, err := audit.AppendIfEnabled(e); err != nil {\n    log.Fatal(err) // \"failed to write interactions log entry: no space left on device\"\n}\n// after\nif _, err := audit.AppendIfEnabled(e); err != nil {\n    if strings.Contains(err.Error(), \"no space left\") {\n        pruneAuditLog(\".beads/interactions.jsonl\") // rotate/truncate\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"var st syscall.Statfs_t\nif err := syscall.Statfs(\".beads\", &st); err == nil && st.Bavail*uint64(st.Bsize) < 1<<20 {\n    return fmt.Errorf(\"low disk space for audit log\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := audit.AppendIfEnabled(e); err != nil {\n    if strings.Contains(err.Error(), \"failed to write interactions log entry\") {\n        log.Printf(\"audit write failed (disk full?): %v\", err)\n    }\n    return err\n}","preventionTips":["Monitor free space on the volume holding .beads/.","Rotate/truncate interactions.jsonl before it grows unbounded.","Avoid audit logging to network filesystems prone to EIO.","Set disk-space alerts in CI runners."],"tags":["go","filesystem","io","audit-log","disk-full"],"backgroundTag":"disk-full","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}