{"record":{"id":"a98902ba9b65677b","repo":"JuliusBrussee/caveman","slug":"supersede-commit-w","errorCode":null,"errorMessage":"supersede commit: %w","messagePattern":"supersede commit: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mem/store.go","lineNumber":257,"sourceCode":"\t\t VALUES (?, ?, ?, ?, ?)`,\n\t\tnewID, newText, now, now, oldID,\n\t); err != nil {\n\t\treturn Memory{}, fmt.Errorf(\"insert replacement memory: %w\", err)\n\t}\n\tres, err := tx.Exec(\n\t\t`UPDATE memories\n\t\t    SET valid_until = ?, superseded_by = ?\n\t\t  WHERE id = ? AND valid_until IS NULL`,\n\t\tnow, newID, oldID,\n\t)\n\tif err != nil {\n\t\treturn Memory{}, fmt.Errorf(\"expire old memory: %w\", err)\n\t}\n\tif n, _ := res.RowsAffected(); n != 1 {\n\t\treturn Memory{}, fmt.Errorf(\"memory %s changed during supersede\", oldID)\n\t}\n\tif err := tx.Commit(); err != nil {\n\t\treturn Memory{}, fmt.Errorf(\"supersede commit: %w\", err)\n\t}\n\treturn Memory{\n\t\tID:         newID,\n\t\tText:       newText,\n\t\tCreatedAt:  now,\n\t\tValidFrom:  now,\n\t\tSupersedes: oldID,\n\t}, nil\n}\n\nfunc validateMemorySize(text string) error {\n\tif len(text) > MaxMemoryBytes {\n\t\treturn fmt.Errorf(\"%w: memory is %d bytes, over the %d-byte cap\", ErrMemoryTooLarge, len(text), MaxMemoryBytes)\n\t}\n\treturn nil\n}\n\n// History returns the complete oldest-to-newest supersession chain containing","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/mem/store.go#L239-L275","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmem, err := store.Supersede(oldID, text)\nif err != nil { panic(err) }\n// after\nmem, err := store.Supersede(oldID, text)\nif err != nil && strings.Contains(err.Error(), \"supersede commit\") {\n\tmem, err = store.Supersede(oldID, text) // safe: tx rolled back\n}","handlingStrategy":"retry","validationCode":"if free, err := diskFree(storeDir); err != nil || free < minFree { return fmt.Errorf(\"low disk\") }","typeGuard":null,"tryCatchPattern":"_, err := store.Supersede(oldID, text)\nif err != nil && strings.Contains(err.Error(), \"supersede commit\") {\n\treturn store.Supersede(oldID, text) // tx rolled back; state consistent\n}","preventionTips":["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"],"tags":["database","sqlite","transaction"],"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"}