clockworklabs/SpacetimeDB · error · anyhow::Error

Removing schedules is not yet implemented

Error message

Removing schedules is not yet implemented

What it means

The mirror of AddSchedule: when the new module removes a scheduled reducer that existed in the previous version, the auto-migrator emits AutoMigrateStep::RemoveSchedule, whose handler is explicitly unimplemented and bails. Any publish that drops a schedule aborts the migration.

Source

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

                        TableAccess::Private
                    }
                };
                stdb.alter_table_access(tx, &table_name, access.into())?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::ChangePrimaryKey(table_name_key) => {
                let (namespace, local) = table_name_key;
                let table_name = joined(namespace, local);
                let (_owning_def, table_def) = plan.new.find_table(table_name_key).ok_or_else(|| {
                    anyhow::anyhow!("ChangePrimaryKey: table `{table_name}` not found in new module def")
                })?;
                log!(logger, "Changing primary key for table `{table_name}`");
                stdb.alter_table_primary_key(tx, &table_name, table_def.primary_key)?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::AddSchedule(_) => {
                anyhow::bail!("Adding schedules is not yet implemented");
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::RemoveSchedule(_) => {
                anyhow::bail!("Removing schedules is not yet implemented");
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::AddRowLevelSecurity(sql_rls) => {
                log!(logger, "Adding row-level security `{sql_rls}`");
                let rls = plan.new.lookup::<RawRowLevelSecurityDefV9>(sql_rls).ok_or_else(|| {
                    anyhow::anyhow!("AddRowLevelSecurity: RLS `{sql_rls}` not found in new module def")
                })?;
                let rls = RowLevelExpr::build_row_level_expr(tx, &auth_ctx, rls)?;

                stdb.create_row_level_security(tx, rls.def)?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::RemoveRowLevelSecurity(sql_rls) => {
                log!(logger, "Removing row-level security `{sql_rls}`");
                stdb.drop_row_level_security(tx, sql_rls.clone())?;
            }
            spacetimedb_schema::auto_migrate::AutoMigrateStep::AddColumns(table_name_key) => {
                let (namespace, local) = table_name_key;
                let table_name = joined(namespace, local);
                let (owning_def, table_def) = plan

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. In development, delete and republish the database so the schedule is absent from the initial schema (spacetime delete <db> && spacetime publish <db>).
  2. Keep the schedule declared but make the reducer a no-op (early return) so the schema diff contains no RemoveSchedule step.
  3. For data-preserving changes, write a manual migration with spacetime migrate instead of relying on auto-migrate.

Example fix

// before: deleting the scheduled reducer triggers RemoveSchedule
// (remove `#[spacetimedb::scheduled(reducer = every_10s)] pub struct Tick;`)
spacetime publish my-db // fails

// after: neutralize the schedule instead of removing it
#[spacetimedb::scheduled(reducer = every_10s)]
pub struct Tick;

#[spacetimedb::reducer]
fn every_10s(_ctx: &ReducerContext, _tick: Tick) {
    // intentionally disabled
}
Defensive patterns

Strategy: fallback

Validate before calling

# before publishing, check whether the diff removes a scheduled reducer:
git diff HEAD~1 -- module/ | grep -E '^\-.*spacetimedb::scheduled'
# a removed schedule means auto-migrate will bail

Try / catch

match publish(&db, &module).await {
    Err(e) if e.to_string().contains("Removing schedules is not yet implemented") => {
        // keep the schedule declared with a no-op reducer, or recreate the db
    }
    other => other,
}

Prevention

When it happens

Trigger: Publishing a module version that deletes or comments out a #[spacetimedb::scheduled] reducer/schedule table that the previously published version had.

Common situations: Removing a periodic cleanup job from a deployed module; refactoring scheduled logic away; disabling a tick reducer during debugging and republishing.

Related errors


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