JuliusBrussee/caveman · error
supersede commit
Error message
supersede commit: %w
What it means
Supersede built the complete lineage change (insert new version, expire old one) but the final tx.Commit() failed, so nothing was persisted. Because it is the last step, this error means the whole supersede was rolled back and the store is unchanged.
Solutions
- Free disk space and check filesystem/journal write permissions.
- Retry the Supersede — the transaction rolled back, so state is consistent.
- Enable busy_timeout so concurrent writers don't block the commit.
- Check SQLite journal mode/WAL configuration and device health.
Example fix
// before
mem, err := store.Supersede(oldID, text)
if err != nil { panic(err) }
// after
mem, err := store.Supersede(oldID, text)
if err != nil && strings.Contains(err.Error(), "supersede commit") {
mem, err = store.Supersede(oldID, text) // safe: tx rolled back
} Defensive patterns
Strategy: retry
Validate before calling
if free, err := diskFree(storeDir); err != nil || free < minFree { return fmt.Errorf("low disk") } Try / catch
_, err := store.Supersede(oldID, text)
if err != nil && strings.Contains(err.Error(), "supersede commit") {
return store.Supersede(oldID, text) // tx rolled back; state consistent
} Prevention
- Keep ample free disk space for SQLite journal/WAL writes
- Enable busy_timeout so commits aren't blocked by other writers
- Monitor storage device health for I/O errors
- Retry once on commit failures — the operation is atomic and safe to repeat
When it happens
Trigger: Calling Store.Supersede(oldID, newText) when SQLite cannot commit the transaction: disk full at journal time, I/O error, database locked at commit, or process-level interruption.
Common situations: Disk filling up between the INSERT and COMMIT; another connection grabbing a lock that blocks the commit; journal/WAL write permission problems; storage device errors.
Related errors
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/a98902ba9b65677b.
Report an issue: GitHub.
Appendix: source
Thrown at mem/store.go:257
VALUES (?, ?, ?, ?, ?)`,
newID, newText, now, now, oldID,
); err != nil {
return Memory{}, fmt.Errorf("insert replacement memory: %w", err)
}
res, err := tx.Exec(
`UPDATE memories
SET valid_until = ?, superseded_by = ?
WHERE id = ? AND valid_until IS NULL`,
now, newID, oldID,
)
if err != nil {
return Memory{}, fmt.Errorf("expire old memory: %w", err)
}
if n, _ := res.RowsAffected(); n != 1 {
return Memory{}, fmt.Errorf("memory %s changed during supersede", oldID)
}
if err := tx.Commit(); err != nil {
return Memory{}, fmt.Errorf("supersede commit: %w", err)
}
return Memory{
ID: newID,
Text: newText,
CreatedAt: now,
ValidFrom: now,
Supersedes: oldID,
}, nil
}
func validateMemorySize(text string) error {
if len(text) > MaxMemoryBytes {
return fmt.Errorf("%w: memory is %d bytes, over the %d-byte cap", ErrMemoryTooLarge, len(text), MaxMemoryBytes)
}
return nil
}
// History returns the complete oldest-to-newest supersession chain containingView on GitHub (pinned to 3ee70a1026)