remix-run/remix · error · Error

Migration directory " " 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.

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.

Appendix: 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)