JuliusBrussee/caveman · error
memory %s not found
Error message
memory %s not found
What it means
The internal lookup memoryByID found no row with the given id (sql.ErrNoRows). Every public path built on it — History, Supersede's target fetch, Forget-style operations — surfaces this as 'memory <id> not found'. It means the id is well-formed but absent from the memories table (or already deleted).
Source
Thrown at mem/store.go:647
&validUntil,
&supersedes,
&supersededBy,
); err != nil {
return err
}
if validUntil.Valid {
memory.ValidUntil = &validUntil.String
}
memory.Supersedes = supersedes.String
memory.SupersededBy = supersededBy.String
return nil
}
func (s *Store) memoryByID(id string) (Memory, error) {
var memory Memory
if err := scanMemory(s.db.QueryRow(memorySelect+` WHERE id = ?`, id), &memory); err != nil {
if err == sql.ErrNoRows {
return Memory{}, fmt.Errorf("memory %s not found", id)
}
return Memory{}, fmt.Errorf("read memory %s: %w", id, err)
}
return memory, nil
}
// migrateMemorySchema upgrades pre-supersession stores in place. SQLite cannot
// add several columns in one statement, so each missing column is added
// independently and legacy created_at becomes valid_from.
func migrateMemorySchema(db *sql.DB) error {
rows, err := db.Query(`PRAGMA table_info(memories)`)
if err != nil {
return err
}
columns := map[string]bool{}
for rows.Next() {
var cid int
var name, kind stringView on GitHub (pinned to 27d5a3981a)
Solutions
- Verify the id exists before acting: query the row or call a lookup and handle absence explicitly
- Check which store file you are attached to — differing CAVEMAN_HOME/data paths between writer and reader is the usual cause
- If the memory was deleted, decide whether to recreate it (Remember) or skip the operation; do not loop-retry a not-found
Example fix
// before
hist, err := store.History(memID) // stale id from an old DB
// after
if _, err := store.History(memID); err != nil {
if strings.HasSuffix(err.Error(), "not found") {
// re-create or skip gracefully
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := store.History(id); err != nil { /* presence check, or cache the result */ } Type guard
func isNotFound(err error) bool {
return err != nil && strings.HasSuffix(err.Error(), "not found")
} Try / catch
hist, err := store.History(id)
if err != nil {
if isNotFound(err) {
// skip, re-create via Remember, or ask the user — do not retry
}
return err
} Prevention
- Pin a single store path (CAVEMAN_HOME) across all writers and readers
- Treat persisted ids as perishable: re-validate before use after restarts
- Distinguish not-found from transient IO errors before choosing a recovery path
When it happens
Trigger: Calling History(id) / Supersede(oldID, ...) / anything resolving a single memory with an id that was never inserted, was Forget-deleted, or came from a different database file. Also when an id string is truncated or has trailing whitespace/encoding damage so the exact match fails.
Common situations: Persisting ids across restarts while the store was recreated or pointed at another path (CAVEMAN_HOME change); using an id from a test fixture against the production DB; retrying an operation whose earlier attempt already deleted the memory.
Related errors
- cave_memory_too_large
- memory %s changed during supersede
- ErrMemoryTooLarge
- history requires memory id
- cyclic supersession history at %s
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/60883e063428a838.
Report an issue: GitHub.