{"record":{"id":"4c206ecc44f4cf34","repo":"spacedriveapp/spacedrive","slug":"failed-to-update-entry","errorCode":null,"errorMessage":"Failed to update entry: {}","messagePattern":"Failed to update entry: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/src/ops/indexing/change_detection/persistent.rs","lineNumber":270,"sourceCode":"\t\tlet entry = entities::entry::Entity::find_by_id(entry_id)\n\t\t\t.one(&self.db)\n\t\t\t.await?\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"Entry not found after creation\"))?;\n\n\t\tOk(EntryRef {\n\t\t\tid: entry.id,\n\t\t\tuuid: entry.uuid,\n\t\t\tpath: metadata.path.clone(),\n\t\t\tkind: metadata.kind,\n\t\t})\n\t}\n\n\tasync fn update(&mut self, entry: &EntryRef, metadata: &DirEntry) -> Result<()> {\n\t\tuse crate::ops::indexing::database_storage::DatabaseStorage;\n\n\t\tDatabaseStorage::update_entry(&self.db, entry.id, metadata)\n\t\t\t.await\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Failed to update entry: {}\", e))?;\n\n\t\tOk(())\n\t}\n\n\tasync fn move_entry(\n\t\t&mut self,\n\t\tentry: &EntryRef,\n\t\told_path: &Path,\n\t\tnew_path: &Path,\n\t\tnew_parent_path: &Path,\n\t) -> Result<()> {\n\t\tuse crate::domain::addressing::SdPath;\n\t\tuse crate::ops::indexing::database_storage::DatabaseStorage;\n\t\tuse crate::ops::indexing::state::IndexerState;\n\n\t\tlet mut state = IndexerState::new(&SdPath::local(old_path));\n\n\t\t// Cache Management: Check cache first, then query DB if needed","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/indexing/change_detection/persistent.rs#L252-L288","documentation":"DatabaseStorage::update_entry failed while applying new metadata (size, modified, kind) to an existing entry during change detection; the sea_orm error is wrapped with the entry id available in EntryRef. The entry was found moments earlier, so failures are usually write-side: locks, constraints, or the row disappearing mid-update.","triggerScenarios":"Entry deleted between find_by_path and update; DB busy/locked under concurrent writers; a constraint triggered by the new metadata values.","commonSituations":"Rapid modify-then-delete sequences from the watcher; multiple indexer jobs on one library; long transactions from another component holding write locks.","solutions":["Read the wrapped inner error to distinguish 'row not found' ( benign race, delete already handled it) from lock/constraint failures","Treat update-of-deleted-row as success (Ok(())) since the delete path owns the state now","Serialize indexing jobs per library to reduce write contention"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = DatabaseStorage::update_entry(&self.db, entry.id, metadata).await {\n    if e.to_string().contains(\"RecordNotFound\") || e.to_string().contains(\"0 rows\") {\n        // entry deleted concurrently; delete path owns the state now\n        return Ok(());\n    }\n    return Err(anyhow::anyhow!(\"Failed to update entry: {}\", e));\n}","preventionTips":["Treat update-of-deleted-row as success in change-detection handlers","Reduce concurrent writer count per library (job serialization)","Log entry ids on update failures to correlate with concurrent deletes"],"tags":["indexing","database","update","race-condition","change-detection"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}