spacedriveapp/spacedrive · error

Entry {} not found after ID lookup

Error message

Entry {} not found after ID lookup

What it means

find_by_path first resolves a path to an entry id via resolve_entry_id, then loads that id with find_by_id. This error means resolution returned Some(id) but the row is gone by the time the SELECT runs: a delete, a reindex that rewrote rows, or a stale closure/path mapping referencing a dead id. The two-step lookup is inherently racy under concurrent writes.

Source

Thrown at core/src/ops/indexing/change_detection/persistent.rs:166

		}

		let model = q.one(&self.db).await?;
		Ok(model.map(|m| m.id))
	}
}

#[async_trait::async_trait]
impl ChangeHandler for DatabaseAdapter {
	async fn find_by_path(&self, path: &Path) -> Result<Option<EntryRef>> {
		let entry_id = match self.resolve_entry_id(path).await? {
			Some(id) => id,
			None => return Ok(None),
		};

		let entry = entities::entry::Entity::find_by_id(entry_id)
			.one(&self.db)
			.await?
			.ok_or_else(|| anyhow::anyhow!("Entry {} not found after ID lookup", entry_id))?;

		let kind = match entry.kind {
			0 => EntryKind::File,
			1 => EntryKind::Directory,
			2 => EntryKind::Symlink,
			_ => EntryKind::File,
		};

		Ok(Some(EntryRef {
			id: entry.id,
			uuid: entry.uuid,
			path: path.to_path_buf(),
			kind,
		}))
	}

	async fn find_by_inode(&self, inode: u64) -> Result<Option<EntryRef>> {
		let inode_val = inode as i64;

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Treat the missing row as 'not found' (return Ok(None)) so the pipeline recreates the entry instead of failing
  2. Check for concurrent reindex/delete jobs running against the same library
  3. Verify delete paths also clean entry_closure rows so resolution cannot return dead ids

Example fix

// before
let entry = entities::entry::Entity::find_by_id(entry_id)
    .one(&self.db)
    .await?
    .ok_or_else(|| anyhow::anyhow!("Entry {} not found after ID lookup", entry_id))?;

// after: a vanished row is a normal race, not a hard failure
let Some(entry) = entities::entry::Entity::find_by_id(entry_id)
    .one(&self.db)
    .await?
else {
    return Ok(None);
};
Defensive patterns

Strategy: try-catch

Try / catch

// A vanished row after id resolution is a benign race: treat as not-found
let entry = match entities::entry::Entity::find_by_id(entry_id).one(&db).await? {
    Some(e) => e,
    None => return Ok(None), // caller will recreate the entry
};

Prevention

When it happens

Trigger: A watcher event for a path whose entry was just deleted by another worker; reindex rebuilding the entry table between the id resolution and the row fetch; stale entry_closure rows pointing at removed ids.

Common situations: Concurrent indexer and watcher pipelines on the same library; a location being reindexed while change events stream in; crashed delete that removed the entry but not closure rows.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/c76379ef27220c92. Report an issue: GitHub.