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
- Create up.sql in the flagged directory with the forward SQL (e.g. CREATE TABLE ...)
- Check .gitignore / git status to be sure up.sql is actually committed
- 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
- Always use the migration generator rather than hand-creating directories
- Ensure up.sql is committed (check .gitignore) and named exactly lowercase
- Run migrations in CI on a case-sensitive filesystem (Linux) to catch naming issues
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
- Duplicate migration id "{id}" inferred from directory "{dire
- expected promise to resolve, but it rejected with: ${stringi
- ${optionName} values must be package names. Received "${pack
- Resolved path escapes the allowed root: ${relativePath}
- Expected a Remix config file or directory: ${fromPath}
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/c2649221233f3480.
Report an issue: GitHub.