slopus/happy · critical
Failed to apply ${dir}: ${e.message}
Error message
Failed to apply ${dir}: ${e.message} What it means
During standalone server startup, runMigrations applies SQL migration directories from the migrations folder. For each migration it inserts a row into the _prisma_migrations table; if any statement fails, the error is rethrown with the migration directory name and the underlying database message appended.
Source
Thrown at packages/happy-server/sources/standalone.ts:98
}
const sqlFile = path.join(migrationsDirResolved, dir, "migration.sql");
if (!fs.existsSync(sqlFile)) {
continue;
}
console.log(` Applying ${dir}...`);
const sql = fs.readFileSync(sqlFile, "utf-8");
try {
await pg.exec(sql);
await pg.query(
`INSERT INTO "_prisma_migrations" ("id", "migration_name", "finished_at", "applied_steps_count") VALUES ($1, $2, now(), 1)`,
[crypto.randomUUID(), dir]
);
appliedCount++;
} catch (e: any) {
throw new Error(`Failed to apply ${dir}: ${e.message}`);
}
}
if (appliedCount === 0) {
console.log("No new migrations to apply.");
} else {
console.log(`Applied ${appliedCount} migration(s).`);
}
await pg.close();
}
async function serve() {
// Ensure DB_PROVIDER is set for db.ts
process.env.DB_PROVIDER = process.env.DB_PROVIDER || "pglite";
process.env.PGLITE_DIR = process.env.PGLITE_DIR || pgliteDir;
const masterSecret = process.env.HANDY_MASTER_SECRET;View on GitHub (pinned to b824cd0a46)
Solutions
- Read the wrapped e.message in the thrown error to identify the failing SQL and fix or revert that migration file
- Verify the target database state (SELECT * FROM _prisma_migrations) and remove bogus rows or reset the database if safe
- Ensure migration files are ordered lexicographically/sequentially and no migration was skipped
- Re-run startup with a freshly created database (or dev/test DB) to confirm migrations apply cleanly
Example fix
// before
throw new Error(`Failed to apply ${dir}: ${e.message}`);
// after
console.error(`Migration ${dir} failed:`, e);
throw new Error(`Failed to apply migration ${dir}: ${e.message}`, { cause: e }); Defensive patterns
Strategy: try-catch
Validate before calling
const applied = await pg.query(`SELECT migration_name FROM "_prisma_migrations"`); const pending = dirs.filter(d => !applied.rows.some(r => r.migration_name === d)); if (pending.length === 0) return;
Try / catch
try {
await runMigrations();
} catch (e) {
if (String(e.message).startsWith('Failed to apply ')) {
const dir = e.message.split(' ')[3];
console.error(`Fix migration ${dir} before retrying`, { cause: e.cause });
}
process.exit(1);
} Prevention
- Keep migration files immutable once applied — never edit applied migrations
- Test migrations against a fresh database copy in CI before deploying
- Check _prisma_migrations table state before manual schema changes
- Run a single migration ordering/sequence check before releases
When it happens
Trigger: A migration SQL file raises a database error (syntax error, conflicting schema, duplicate table/column, constraint violation) when executed against the configured database, and the INSERT INTO _prisma_migrations bookkeeping also fails or the migration body throws inside the try block.
Common situations: Applying migrations to a database that was partially migrated by hand; running an older/newer set of migration files against an existing DB; dialect mismatches (Postgres-only SQL against PGlite); corrupted or out-of-order migration directories.
Related errors
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/b62d51f9be05567c.
Report an issue: GitHub.