clockworklabs/SpacetimeDB · error

ChangeIndexSourceName: `{index_name}` not found in old modul

Error message

ChangeIndexSourceName: `{index_name}` not found in old module def

What it means

Applying AutoMigrateStep::ChangeIndexSourceName: the planner decided an index's source name changed (e.g. the column/type accessor feeding the index was renamed), but plan.old.find_storing_table(namespace, index_name) cannot find any table in the old module def that stores this index. The step's key does not resolve in the old defs, so stored and new index metadata cannot be compared. The publish aborts.

Source

Thrown at crates/engine/src/update.rs:419

                    .columns
                    .iter()
                    .find(|col| &col.col_name == col_name)
                    .ok_or_else(|| anyhow::anyhow!("Column `{col_name}` not found in table `{table_name}`"))?;

                log!(
                    logger,
                    "Changing column accessor name for `{}`.`{}` to `{}`",
                    table_name,
                    col_name,
                    new_col_def.accessor_name,
                );
                stdb.alter_column_accessor_name(tx, table_id, col_schema.col_pos, new_col_def.accessor_name.clone())?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangeIndexSourceName(key) => {
                let (namespace, index_name) = key;
                let (_old_owning_def, old_table_def) =
                    plan.old.find_storing_table(namespace, index_name).ok_or_else(|| {
                        anyhow::anyhow!("ChangeIndexSourceName: `{index_name}` not found in old module def")
                    })?;
                let (_new_owning_def, new_table_def) =
                    plan.new.find_storing_table(namespace, index_name).ok_or_else(|| {
                        anyhow::anyhow!("ChangeIndexSourceName: `{index_name}` not found in new module def")
                    })?;
                let table_full_name = joined(namespace, &old_table_def.name);
                let stored_name = namespace.join_raw(&index_name.clone().into());
                let new_index_def = new_table_def
                    .indexes
                    .get(index_name)
                    .ok_or_else(|| anyhow::anyhow!("Index `{index_name}` not found in table `{table_full_name}`"))?;

                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)

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Clean-rebuild and republish (cargo clean, spacetime build, spacetime publish <db>).
  2. Split the change: rename the indexed column in one publish; change index names/locations in another.
  3. Pin index and column names (#[index(name = "...")], #[column(name = "...")]) so keys stay stable.
  4. Match the toolchain version that created the database before attempting structural index changes.
  5. Dev: spacetime publish --delete-data <db>.
  6. File a SpacetimeDB issue with the plan if clean builds reproduce it.

Example fix

// before: index source renamed AND index/table restructured in one publish
#[spacetimedb::index(name = "by_hp", btree)] // source column `hp` renamed same publish

// after: pin names, publish the source rename alone first
#[spacetimedb::table(name = "players")]
pub struct Player {
    #[spacetimedb::column(name = "hp")]
    #[spacetimedb::index(btree)]
    pub hit_points: u32,
}
Defensive patterns

Strategy: fallback

Validate before calling

use spacetimedb_schema::auto_migrate::AutoMigrateStep;
for step in &plan.steps {
    if let AutoMigrateStep::ChangeIndexSourceName((namespace, index_name)) = step {
        if plan.old.find_storing_table(namespace, index_name).is_none() {
            anyhow::bail!("old def lacks index {} - stored schema drift", index_name);
        }
    }
}

Type guard

fn index_in_old_def<'a>(plan: &'a AutoMigratePlan, ns: &str, idx: &str) -> bool {
    plan.old.find_storing_table(ns, idx).is_some()
}

Try / catch

match update_database(&stdb, tx, &plan, ...).await {
    Err(e) if e.to_string().contains("ChangeIndexSourceName")
        && e.to_string().contains("old module def") => {
        // Fall back: republish the exact previous build, then migrate the index stepwise.
    }
    result => result?,
}

Prevention

When it happens

Trigger: Renaming the column or accessor an index is built on while also renaming/dropping the index or its table in one publish; or the old-def reconstruction differs from the schema the live database was published with (auto-generated index names differ across compiler versions).

Common situations: Renaming indexed columns together with #[index(...)] edits; republishing databases created by older spacetimedb compilers that auto-named indexes differently; moving indexed tables into submodules.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/12312fc338dcf2a3. Report an issue: GitHub.