remix-run/remix · error · Error

Migration directory "{directoryName}" is missing up.sql

Error message

Migration directory "{directoryName}" is missing up.sql

What it means

Each migration directory must contain an up.sql file defining the forward migration. loadMigrations reads it with fs.readFile and, when the failure is a Node ENOENT (file not found), throws an Error stating the directory is missing up.sql. down.sql is optional, but up.sql is mandatory.

Source

Thrown at packages/data-table/src/lib/migrations-node.ts:58

          parsed.id +
          '" inferred from directory "' +
          directoryName +
          '"',
      )
    }

    seenIds.add(parsed.id)

    let directoryPath = path.join(directory, directoryName)
    let upPath = path.join(directoryPath, 'up.sql')
    let downPath = path.join(directoryPath, 'down.sql')

    let up: string
    try {
      up = await fs.readFile(upPath, 'utf8')
    } catch (error) {
      if (isNodeFileNotFoundError(error)) {
        throw new Error('Migration directory "' + directoryName + '" is missing up.sql')
      }
      throw error
    }

    let down: string | undefined
    try {
      down = await fs.readFile(downPath, 'utf8')
    } catch (error) {
      if (!isNodeFileNotFoundError(error)) {
        throw error
      }
    }

    migrations.push({
      id: parsed.id,
      name: parsed.name,
      up,
      down,

View on GitHub (pinned to 9696913134)

Solutions

  1. Create up.sql in the flagged directory with the forward SQL (e.g. CREATE TABLE ...)
  2. Check .gitignore / git status to be sure up.sql is actually committed
  3. Verify the filename is exactly up.sql with lowercase extension

Example fix

# before
migrations/20240101000000_add_users/
  down.sql

# after
migrations/20240101000000_add_users/
  up.sql     # CREATE TABLE users (...);
  down.sql
Defensive patterns

Strategy: validation

Validate before calling

for (let dir of directories) {
  if (!existsSync(path.join(migrationsDir, dir, 'up.sql'))) {
    throw new Error(`${dir} is missing up.sql`)
  }
}

Type guard

function isCompleteMigrationDirectory(files: string[]): boolean {
  return files.includes('up.sql')
}

Prevention

When it happens

Trigger: A migration directory containing only down.sql, a .gitkeep, or nothing; committing a migration before creating up.sql; typos in the filename (Up.sql, up.TXT) which read as missing on case-sensitive filesystems.

Common situations: Partial commits where up.sql was ignored by .gitignore; hand-creating a migration directory without the generator; renaming files with editors that change case; deploying to Linux after developing on macOS/Windows (case sensitivity).

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/c2649221233f3480. Report an issue: GitHub.