gofr-dev/gofr · error
failed to create migration directory %q: %w
Error message
failed to create migration directory %q: %w
What it means
Thrown by checkAndCreateMigrationTable when os.MkdirAll cannot create the directory that should contain the OpenTSDB migration file. The wrapped error identifies the OS-level cause (permissions, path is a file, read-only FS). Migration setup aborts before any migration runs.
Source
Thrown at pkg/gofr/migration/opentsdb.go:56
// apply initializes openTSDBMigrator using the openTsdbDS.
func (ds openTSDBDS) apply(m migrator) migrator {
return &openTSDBMigrator{ // Return pointer to avoid copying the mutex
filePath: ds.filePath,
migrator: m,
}
}
// checkAndCreateMigrationTable ensures the migration directory and file structure exists.
// It only creates an empty file if no migration file exists at all.
func (om *openTSDBMigrator) checkAndCreateMigrationTable(c *container.Container) error {
om.mu.Lock()
defer om.mu.Unlock()
// Ensure directory exists
dir := filepath.Dir(om.filePath)
if dir != "." {
if err := os.MkdirAll(dir, dirPerm); err != nil {
return fmt.Errorf("failed to create migration directory %q: %w", dir, err)
}
}
// Check if file exists and is readable
if _, err := os.Stat(om.filePath); err == nil {
// File exists, validate it's proper JSON
return om.validateExistingFile(c)
} else if !os.IsNotExist(err) {
// Some other error accessing the file
return fmt.Errorf("unexpected error stating migration file: %w", err)
}
// File doesn't exist, create empty migration file
return om.createEmptyMigrationFile(c)
}
// validateExistingFile checks if the existing migration file is valid JSON.
func (om *openTSDBMigrator) validateExistingFile(c *container.Container) error {View on GitHub (pinned to 187eb24962)
Solutions
- Make the parent directory writable or choose a writable filePath (e.g. /var/lib/app)
- Check the wrapped OS error — EACCES vs ENOTDIR vs EROFS
- Remove/replace any regular file that conflicts with the directory path
- Pre-create the directory with correct ownership before deploying
Example fix
// before filePath: "/etc/gofr_migrations.json" // MkdirAll(/etc) fails: permission denied // after filePath: "/var/lib/myapp/gofr_migrations.json"
Defensive patterns
Strategy: validation
Validate before calling
dir := filepath.Dir(cfg.OpenTSDBMigrationFile)
if info, err := os.Stat(dir); err == nil && !info.IsDir() {
return fmt.Errorf("%s exists but is a file; remove it so a directory can be created", dir)
}
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("pre-flight mkdir failed: %w", err)
} Prevention
- Never place the migration file under system dirs like /etc or /usr
- Ensure no regular file occupies the would-be directory path
- Grant the app user write permission on the parent path
- Run pre-flight mkdir in your deployment script before the app starts
When it happens
Trigger: filepath.Dir(om.filePath) is not "." and os.MkdirAll(dir, 0755) fails: parent not writable, a path component exists as a regular file, or the filesystem is read-only.
Common situations: filePath configured as /etc/gofr_migrations.json (no write perms); a file occupies what should be a directory; running in a locked-down container rootfs; NFS mount gone read-only.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- unexpected error stating migration file: %w
- failed to open existing migration file: %w
- failed to create migration file: received nil file handle
- file does not have read permission: %w
- failed to delete object
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/03d2996dfe603ce1.
Report an issue: GitHub.