slopus/happy · critical

Could not find prisma/migrations directory. Tried: ${candida

Error message

Could not find prisma/migrations directory. Tried: ${candidates.join(", ")}

What it means

runMigrations() in the standalone server searches a list of candidate paths for the prisma/migrations directory before running migrations. If none of the candidates exists on disk, it throws with the exact paths it tried, because it cannot locate the SQL migrations to apply.

Source

Thrown at packages/happy-server/sources/standalone.ts:62

    `);

    // Find migrations directory - explicit arg wins; fall back to defaults.
    let migrationsDirResolved = "";
    const candidates: string[] = [];
    if (opts.migrationsDir) candidates.push(opts.migrationsDir);
    candidates.push(
        path.join(process.cwd(), "prisma", "migrations"),
        path.join(process.cwd(), "packages", "happy-server", "prisma", "migrations"),
        path.join(path.dirname(process.execPath), "prisma", "migrations"),
    );
    for (const candidate of candidates) {
        if (fs.existsSync(candidate)) {
            migrationsDirResolved = candidate;
            break;
        }
    }
    if (!migrationsDirResolved) {
        throw new Error(`Could not find prisma/migrations directory. Tried: ${candidates.join(", ")}`);
    }

    // Get all migration directories sorted
    const dirs = fs.readdirSync(migrationsDirResolved)
        .filter(d => fs.statSync(path.join(migrationsDirResolved, d)).isDirectory())
        .sort();

    // Get already applied migrations
    const applied = await pg.query<{ migration_name: string }>(
        `SELECT "migration_name" FROM "_prisma_migrations" WHERE "finished_at" IS NOT NULL`
    );
    const appliedSet = new Set(applied.rows.map(r => r.migration_name));

    let appliedCount = 0;
    for (const dir of dirs) {
        if (appliedSet.has(dir)) {
            continue;
        }

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Run the server from the package root so the relative prisma/migrations path resolves, or set the working directory accordingly.
  2. Copy prisma/migrations into the image/bundle (e.g. COPY prisma ./prisma in the Dockerfile, or add 'prisma' to package.json 'files').
  3. Set the env var/option the candidate list uses (check how candidates are built near standalone.ts:62) to point at the correct migrations path.
  4. Verify with: ls prisma/migrations relative to where you launch the server.
  5. If migrations are managed externally, run 'prisma migrate deploy' yourself and skip embedded migrations.

Example fix

// before (Dockerfile)
COPY dist ./dist
CMD ["node", "dist/standalone.js"]
// after
COPY dist ./dist
COPY prisma ./prisma
CMD ["node", "dist/standalone.js"]
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
function migrationsExist(candidates) {
  const found = candidates.find(c => fs.existsSync(c));
  if (!found) {
    throw new Error(`prisma/migrations not found. CWD=${process.cwd()}. Tried: ${candidates.join(', ')}`);
  }
  return found;
}

Try / catch

try {
  await runMigrations();
} catch (e) {
  if (e.message.startsWith('Could not find prisma/migrations')) {
    console.error('Deployment missing prisma/migrations. CWD:', process.cwd(), e.message);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running the standalone server from a working directory or packaged bundle (Docker image, dist folder) that does not include prisma/migrations; wrong CWD; pruning migrations in a build step.

Common situations: Docker images built without copying the prisma folder; running the compiled server from a different directory than the package root; monorepo builds that resolve relative to the bundle output rather than the package; npm pruning migrations via 'files' in package.json.

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/3c9a2826c873c972. Report an issue: GitHub.