toeverything/AFFiNE · error · Error

Unknown migration name: ${name}.

Error message

Unknown migration name: ${name}.

What it means

Thrown by `RunCommand.runOne` when no collected migration matches the supplied `name`. The migration registry is built from the file modules in `data/migrations`, so a name not present there cannot be run. A plain `Error` (no error code); unlike `RevertCommand`, this variant does not log the available names.

Source

Thrown at packages/backend/server/src/data/commands/run.ts:75

      }

      await this.runMigration(migration);

      done.push(migration);
    }

    this.logger.log(`Done ${done.length} migrations`);
    done.forEach(migration => {
      this.logger.log(`  ✔ ${migration.name}`);
    });
  }

  async runOne(name: string) {
    const migrations = collectMigrations();
    const migration = migrations.find(m => m.name === name);

    if (!migration) {
      throw new Error(`Unknown migration name: ${name}.`);
    }
    const exists = await this.db.dataMigration.count({
      where: {
        name: migration.name,
      },
    });

    if (exists) return;

    await this.runMigration(migration);
  }

  private async runMigration(migration: Migration) {
    this.logger.log(`Running ${migration.name}...`);
    const record = await this.db.dataMigration.upsert({
      where: {
        name: migration.name,
      },

View on GitHub (pinned to 26c515e050)

Solutions

  1. List the migrations directory (`packages/backend/server/src/data/migrations/`) to see available names.
  2. Use the exact filename without extension (and with its trailing numeric suffix).
  3. Trim whitespace from the name before invoking; verify against the registry exports.
  4. If the migration is missing, ensure the file exists and is exported from `data/migrations/index.ts`.

Example fix

// before
await runCommand.runOne('add-indexes');

// after
await runCommand.runOne('1766000000000-add-indexes'); // exact name from registry
Defensive patterns

Strategy: validation

Validate before calling

// Verify the name is in the registry before running
const migrations = collectMigrations();
if (!migrations.find(m => m.name === name)) {
  console.error('Available:', migrations.map(m => m.name).join(', '));
  process.exit(1);
}
await runCommand.runOne(name);

Type guard

function isRegisteredMigration(name, migrations) {
  return migrations.some(m => m.name === name);
}

Try / catch

try {
  await runCommand.runOne(name);
} catch (e) {
  if (e.message.startsWith('Unknown migration name')) {
    const migrations = collectMigrations();
    console.error('Available:', migrations.map(m => m.name).join(', '));
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `runOne(name)` with a typo, a migration that has not been added to the registry, an old name after a rename, or a name from a different version of the codebase.

Common situations: Operator mistypes the migration name; migration was renamed in an upgrade but ops still uses the old name; running against a deployment that doesn't include the new migration file; copy-paste of a name with trailing whitespace.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/d55fc7e315c6016c. Report an issue: GitHub.