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

  1. Read the wrapped e.message in the thrown error to identify the failing SQL and fix or revert that migration file
  2. Verify the target database state (SELECT * FROM _prisma_migrations) and remove bogus rows or reset the database if safe
  3. Ensure migration files are ordered lexicographically/sequentially and no migration was skipped
  4. 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

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.