{"record":{"id":"8f48aa95d8ac34bd","repo":"JuliusBrussee/caveman","slug":"store-memory-w","errorCode":null,"errorMessage":"store memory: %w","messagePattern":"store memory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mem/store.go","lineNumber":185,"sourceCode":"\tif strings.TrimSpace(text) == \"\" {\n\t\treturn Memory{}, fmt.Errorf(\"cannot remember empty text\")\n\t}\n\tif err := validateMemorySize(text); err != nil {\n\t\treturn Memory{}, err\n\t}\n\tid := memID(text)\n\tcreated := time.Now().UTC().Format(time.RFC3339Nano)\n\t// INSERT OR IGNORE keeps the original created_at on a repeat remember.\n\t// RetryOnBusy: under a fan-out of cavemem processes, a queued writer can\n\t// outlast a single busy_timeout (Windows file locking is the slowest case).\n\tif err := ccr.RetryOnBusy(func() error {\n\t\t_, e := s.db.Exec(\n\t\t\t`INSERT OR IGNORE INTO memories (id, text, created_at, valid_from) VALUES (?, ?, ?, ?)`,\n\t\t\tid, text, created, created,\n\t\t)\n\t\treturn e\n\t}); err != nil {\n\t\treturn Memory{}, fmt.Errorf(\"store memory: %w\", err)\n\t}\n\tvar stored Memory\n\trow := s.db.QueryRow(memorySelect+` WHERE id = ?`, id)\n\tif err := scanMemory(row, &stored); err != nil {\n\t\treturn Memory{}, fmt.Errorf(\"read back memory: %w\", err)\n\t}\n\tif stored.ValidUntil != nil {\n\t\treturn Memory{}, fmt.Errorf(\"memory %s exists only as an expired historical version and cannot be re-remembered as current\", stored.ID)\n\t}\n\treturn stored, nil\n}\n\n// Supersede atomically replaces one current memory with a new current version.\n// The old row remains durable for history and byte-exact audit, but normal recall\n// excludes it. An already-expired or unknown id fails closed.\nfunc (s *Store) Supersede(oldID, newText string) (Memory, error) {\n\tif strings.TrimSpace(oldID) == \"\" {\n\t\treturn Memory{}, fmt.Errorf(\"supersede requires old memory id\")","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/mem/store.go#L167-L203","documentation":"Remember() wraps failures from the INSERT OR IGNORE INTO memories statement (run through ccr.RetryOnBusy) with this error. It means the memory text could not be durably written to the SQLite store, so Remember returns no Memory. Because the raw text write is the first durable step, this failure means nothing was remembered.","triggerScenarios":"Calling Remember when the SQLite db is locked beyond the busy-retry budget, the disk is full, the db file is corrupt/read-only, or the schema is missing (e.g. store constructed without Open).","commonSituations":"Concurrent writers to the same memory db (SQLITE_BUSY), running from a read-only container filesystem, disk quota exhaustion, or a corrupted db after an unclean shutdown.","solutions":["Read the wrapped cause: 'database is locked' → reduce concurrent writers or increase retry tolerance; 'readonly database' → fix permissions/mount.","Check free disk space and quotas.","Verify the store was created via mem.Open so the schema exists.","Back up and recreate the db if it is corrupt.","Retry Remember after transient lock contention clears."],"exampleFix":"// before\nm, err := store.Remember(text)\nif err != nil { panic(err) }\n// after\nm, err := store.Remember(text)\nif err != nil {\n    if strings.Contains(err.Error(), \"database is locked\") {\n        time.Sleep(100 * time.Millisecond)\n        m, err = store.Remember(text) // bounded retry\n    }\n    if err != nil { return fmt.Errorf(\"remember %q: %w\", text, err) }\n}","handlingStrategy":"retry","validationCode":"// Go: confirm store is open and db file writable before Remember\nif store == nil { return fmt.Errorf(\"store not open\") }","typeGuard":null,"tryCatchPattern":"m, err := store.Remember(text)\nif err != nil {\n    if strings.Contains(err.Error(), \"database is locked\") {\n        time.Sleep(backoff); m, err = store.Remember(text) // bounded retries\n    }\n    if err != nil { return err }\n}","preventionTips":["Minimize concurrent writers to the same memory db","Monitor disk space and file permissions","Always construct the Store via mem.Open so schema exists","Use bounded retry with backoff for transient SQLITE_BUSY"],"tags":["database","sqlite","write-failure"],"backgroundTag":"database-write-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}