clockworklabs/SpacetimeDB · error
RemoveIndex: `{index_name}` not found in old module def
Error message
RemoveIndex: `{index_name}` not found in old module def What it means
Auto-migrate step RemoveIndex: find_storing_table over plan.old failed — the old module def has no table that stores the index the plan wants to drop. The removal step references an index whose owning table is missing from the old def, an internal plan/old-def inconsistency.
Source
Thrown at crates/engine/src/update.rs:353
.filter_map(|(_, c)| c.data.unique_columns())
.any(|unique_cols| unique_cols == &index_cols);
log!(logger, "Creating index `{index_name}` on table `{table_full_name}`");
let mut index_schema = IndexSchema::from_module_def(owning_def, index_def, table_id, 0.into());
// Apply namespace prefix for submodule indexes
index_schema.index_name = namespace.join_raw(&index_schema.index_name);
index_schema.alias = index_schema.alias.as_ref().map(|alias| namespace.join_raw(alias));
stdb.create_index(tx, index_schema, is_unique)?;
}
spacetimedb_schema::auto_migrate::AutoMigrateStep::RemoveIndex(key) => {
let (namespace, index_name) = key;
let (_owning_def, table_def) = plan
.old
.find_storing_table(namespace, index_name)
.ok_or_else(|| anyhow::anyhow!("RemoveIndex: `{index_name}` not found in old module def"))?;
let table_full_name = joined(namespace, &table_def.name);
let stored_name = namespace.join_raw(&index_name.clone().into());
let table_id = stdb.table_id_from_name_mut(tx, &table_full_name)?.unwrap();
let table_schema = stdb.schema_for_table_mut(tx, table_id)?;
let index_schema = table_schema
.indexes
.iter()
.find(|index| index.index_name == stored_name)
.ok_or_else(|| anyhow::anyhow!("Index `{index_name}` not found in table `{table_full_name}`"))?;
log!(logger, "Dropping index `{index_name}` on table `{table_full_name}`");
stdb.drop_index(tx, index_schema.index_id)?;
}
spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeTableAccessorName(table_name_key) => {
let (namespace, local) = table_name_key;
let table_name = joined(namespace, local);
let (_, new_table_def): (&ModuleDef, &spacetimedb_schema::def::TableDef) =View on GitHub (pinned to 6dee26c6ef)
Solutions
- Regenerate the plan from the old def that matches the currently published module
- Verify the (namespace, index name) key resolves in plan.old before applying
- Report upstream if the differ emitted the stale step
Defensive patterns
Strategy: try-catch
Try / catch
match auto_migrate_database(&stdb, &mut tx, auth, &plan, &logger) {
Err(e) if e.to_string().contains("RemoveIndex:") && e.to_string().contains("not found in old module def") => {
anyhow::bail!("plan/old-def desync: {e:#}; rebuild the plan from the currently published module");
}
r => r,
} Prevention
- Rebuild removal steps against the old def that matches the published module
- Do not cache plans across module versions
- Track def revisions alongside cached plans if caching is unavoidable
When it happens
Trigger: RemoveIndex steps computed against an older def revision where the table existed; the storing table was renamed/removed while the index step survived; hand-built plans with dangling keys.
Common situations: Cached migration plans reused across module edits; upstream differ bugs; submodule reorganization between def versions.
Related errors
- AddIndex: `{index_name}` not found in new module def
- AddIndex: index `{index_name}` not found in new module def
- Precheck: sequence `{sequence_name}` not found in new module
- AddTable: table `{table_name}` not found in new module def
- AddView: view `{view_name}` not found in new module def
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/03221fe90990a04d.
Report an issue: GitHub.