gastownhall/beads · warning

failed to close interactions log: %w

Error message

failed to close interactions log: %w

What it means

When the interactions log does not yet exist, EnsureFile creates it with O_CREATE|O_EXCL and immediately closes it to reserve the file. If that immediate Close returns an error, it is wrapped with 'failed to close interactions log'. This is rare and usually signals an underlying I/O problem rather than a logic issue.

Source

Thrown at internal/audit/audit.go:98

	}
}

// EnsureFile creates .beads/interactions.jsonl if it does not exist.
func EnsureFile() (string, error) {
	p, err := Path()
	if err != nil {
		return "", err
	}
	if err := os.MkdirAll(filepath.Dir(p), 0700); err != nil {
		return "", fmt.Errorf("failed to create .beads directory: %w", err)
	}
	if ensureFileBeforeCreateHook != nil {
		ensureFileBeforeCreateHook(p)
	}
	f, err := os.OpenFile(p, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644) // nolint:gosec // JSONL is intended to be shared via git across clones/tools.
	if err == nil {
		if closeErr := f.Close(); closeErr != nil {
			return "", fmt.Errorf("failed to close interactions log: %w", closeErr)
		}
		return p, nil
	}
	if !errors.Is(err, os.ErrExist) {
		return "", fmt.Errorf("failed to create interactions log: %w", err)
	}
	return p, nil
}

// Append appends an event to .beads/interactions.jsonl as a single JSON line.
// This is intentionally append-only: callers must not mutate existing lines.
func Append(e *Entry) (string, error) {
	if e == nil {
		return "", fmt.Errorf("nil entry")
	}
	if e.Kind == "" {
		return "", fmt.Errorf("kind is required")
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check disk space and filesystem health (dmesg, fsck)
  2. Raise the process file-descriptor limit (ulimit -n) if fd exhaustion is implicated
  3. Retry the operation; if it persists, move the .beads directory to healthy storage
Defensive patterns

Strategy: try-catch

Try / catch

p, err := audit.EnsureFile()
if err != nil {
    if strings.Contains(err.Error(), "failed to close interactions log") {
        log.Printf("transient I/O problem creating audit log: %v", err)
        return retryEnsure()
    }
    return err
}

Prevention

When it happens

Trigger: Creating the audit JSONL file for the first time (no other writer won the O_EXCL race) and the subsequent f.Close() fails due to delayed I/O errors or fd/table exhaustion.

Common situations: Full disks or failing storage surfacing errors at close, containers with low fd limits, or unusual filesystems that report errors on close.

Related errors


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