gastownhall/beads · warning

audit JSONL sidecar is disabled; set audit.enabled=true or B

Error message

audit JSONL sidecar is disabled; set audit.enabled=true or BD_AUDIT_ENABLED=1 to write %s

What it means

AppendIfEnabled gates the audit JSONL sidecar on the audit.enabled config key or the BD_AUDIT_ENABLED environment variable; when disabled it returns this descriptive error instead of writing. First-class issue history is always in the database — this sidecar (interactions.jsonl) is opt-in, so the error tells you exactly which switch to flip. Note this means AppendIfEnabled returns an error in the default configuration, which callers must expect.

Source

Thrown at internal/audit/audit.go:160

	// Using bufio.NewWriter could split into multiple write() syscalls,
	// which interleave under concurrent O_APPEND and corrupt lines.
	var buf bytes.Buffer
	enc := json.NewEncoder(&buf)
	enc.SetEscapeHTML(false)
	if err := enc.Encode(e); err != nil {
		return "", fmt.Errorf("failed to marshal interactions log entry: %w", err)
	}
	if _, err := f.Write(buf.Bytes()); err != nil {
		return "", fmt.Errorf("failed to write interactions log entry: %w", err)
	}

	return e.ID, nil
}

// AppendIfEnabled appends only when the optional JSONL sidecar is enabled.
func AppendIfEnabled(e *Entry) (string, error) {
	if !Enabled() {
		return "", fmt.Errorf("audit JSONL sidecar is disabled; set audit.enabled=true or BD_AUDIT_ENABLED=1 to write %s", FileName)
	}
	return Append(e)
}

// LogFieldChange logs a field change (status, assignee, priority, etc.) to the
// optional JSONL sidecar when it is enabled. First-class issue history is
// recorded separately in the database events tables. Best-effort: errors are
// silently ignored so sidecar logging never blocks operations.
// Optional reason is included when non-empty (e.g., close reason, cleanup rule).
func LogFieldChange(issueID, field, oldValue, newValue, actor, reason string) {
	if oldValue == newValue {
		return
	}
	extra := map[string]any{
		"field":     field,
		"old_value": oldValue,
		"new_value": newValue,
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Set BD_AUDIT_ENABLED=1 in the environment before running the command.
  2. Add audit.enabled = true to the beads config.
  3. Check what Enabled() sees: verify the env var spelling (BD_AUDIT_ENABLED) and truthy spelling (1/true/yes/on).
  4. If the sidecar is intentionally off, treat this error as an expected signal and skip/ignore it in the caller.

Example fix

// before
_, err := audit.AppendIfEnabled(entry) // disabled by default
// after
if audit.Enabled() {
    if _, err := audit.AppendIfEnabled(entry); err != nil {
        return fmt.Errorf("audit: %w", err)
    }
} // or: export BD_AUDIT_ENABLED=1
Defensive patterns

Strategy: type-guard

Validate before calling

if !audit.Enabled() {
    return nil // sidecar intentionally off; skip audit write
}

Type guard

func auditEnabled() bool { return audit.Enabled() }

Try / catch

if _, err := audit.AppendIfEnabled(e); err != nil {
    if strings.Contains(err.Error(), "sidecar is disabled") {
        return nil // expected when audit.enabled=false
    }
    return err
}

Prevention

When it happens

Trigger: Calling AppendIfEnabled (directly or via LogFieldChange) in a repo where audit.enabled is unset/false in config and BD_AUDIT_ENABLED is not a truthy value (1/t/true/y/yes/on).

Common situations: New installs where the sidecar was never enabled; environments where BD_AUDIT_ENABLED was set only in a shell profile not used by the process; config files loaded from a different directory than expected; users expecting audit logging by default.

Related errors


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