paperclipai/paperclip · error · Error

Migration journal is not a prefix of this Paperclip checkout

Error message

Migration journal is not a prefix of this Paperclip checkout's migration journal.

What it means

resolveWorktreeSeedMigrationRevision() validates that the migrations applied in a database form a contiguous prefix of this checkout's migration journal (packages/db drizzle migrations). It builds expectedAppliedPrefix = availableMigrations sliced to appliedMigrations.length and requires the applied set to match it exactly. A mismatch means the database's journal diverged from this checkout (extra, renamed, reordered, or skipped migrations), so seed/legacy-adoption logic cannot map it to a revision.

Source

Thrown at cli/src/commands/worktree.ts:1478

  deploymentMode: PaperclipConfig["server"]["deploymentMode"],
): boolean {
  return deploymentMode === "authenticated";
}

export function resolveWorktreeSeedMigrationRevision(
  migrationState: Awaited<ReturnType<typeof inspectMigrations>>,
  requirement: "sourcePrefix" | "upToDate",
): string {
  const expectedAppliedPrefix = migrationState.availableMigrations.slice(
    0,
    migrationState.appliedMigrations.length,
  );
  const appliedMigrationNames = new Set(migrationState.appliedMigrations);
  if (
    appliedMigrationNames.size !== expectedAppliedPrefix.length ||
    expectedAppliedPrefix.some((migration) => !appliedMigrationNames.has(migration))
  ) {
    throw new Error("Migration journal is not a prefix of this Paperclip checkout's migration journal.");
  }

  if (requirement === "upToDate" && migrationState.status !== "upToDate") {
    throw new Error(
      `Migration journal is not current (${migrationState.pendingMigrations.length} pending migration(s)).`,
    );
  }

  const migrationRevision = expectedAppliedPrefix.at(-1);
  if (!migrationRevision) {
    throw new Error("Migration journal has no applied revision.");
  }
  return migrationRevision;
}

/**
 * Markerless worktrees predate the versioned seed manifest. Adopt one only
 * after proving that its configured database already has a compatible

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Reseed the worktree from the canonical registered source instead of adopting the divergent database
  2. Check out the exact Paperclip version whose migration journal matches the database, then retry
  3. Diff applied vs available journal entries (drizzle meta/_journal) to find the divergent entry; if the DB is disposable, drop and reseed it
Defensive patterns

Strategy: fallback

Validate before calling

const state = await inspectMigrations(/* target connection */);
const prefixOk =
  state.appliedMigrations.length <= state.availableMigrations.length
  && state.appliedMigrations.every((name, i) => name === state.availableMigrations[i]);
if (!prefixOk) {
  // journal diverged: do not adopt this database; provision a fresh seed
}

Try / catch

Wrap the adopt path in try-catch; on 'not a prefix' fall back to fresh provisioning (markWorktreeSeedPending + clone from the registered source).

Prevention

When it happens

Trigger: Calling resolveWorktreeSeedMigrationRevision(migrationState, 'sourcePrefix' | 'upToDate') during worktree seed validation or inspectLegacyWorktreeDatabase when the database's applied-migration names are not exactly the first N entries of the checkout's journal — e.g. the DB was created by a fork or branch with different/reordered migration files.

Common situations: Worktree databases created from a different branch with reordered migration filenames; cherry-picked commits that changed journal order; a database migrated out of band; a checkout after migration files were renamed.

Related errors


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-21). Data as JSON: /api/errors/fba3760a36e038f8. Report an issue: GitHub.