gofr-dev/gofr · error
unexpected error stating migration file: %w
Error message
unexpected error stating migration file: %w
What it means
Returned by checkAndCreateMigrationTable when os.Stat on the migration file fails with an error other than 'not exists' — e.g. permission denied on the path or an I/O error. The migrator can neither read nor safely create the file, so it aborts. Note the message's likely typo ('stating' for 'stat-ing').
Source
Thrown at pkg/gofr/migration/opentsdb.go:66
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 {
file, err := os.Open(om.filePath)
if err != nil {
return fmt.Errorf("failed to open existing migration file: %w", err)
}
defer file.Close()
var migrations []tsdbMigrationRecord
if err = json.NewDecoder(file).Decode(&migrations); err != nil {
c.Errorf("Existing migration file is corrupted: %v", err)
return fmt.Errorf("existing migration file contains invalid JSON: %w", err)View on GitHub (pinned to 187eb24962)
Solutions
- Read the wrapped OS errno to identify the stat failure
- Fix permissions on the file and its parent directories (0755 dir, owner write)
- Replace broken symlinks and verify the mount is healthy
- Adjust SELinux/AppArmor policies if they block stat on the path
Example fix
// before ls -l /data/gofr_migrations.json // owned by root, app runs as appuser -> stat EACCES // after chown appuser:appuser /data/gofr_migrations.json && chmod 644 /data/gofr_migrations.json
Defensive patterns
Strategy: validation
Validate before calling
p := cfg.OpenTSDBMigrationFile
if _, err := os.Stat(p); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("migration file path has access problems (check perms/symlink): %w", err)
}
if info, err := os.Lstat(p); err == nil && info.Mode()&os.ModeSymlink != 0 {
return errors.New("migration file is a symlink; verify target")
} Prevention
- Verify file ownership and mode after any manual edits to the migration file
- Avoid symlinks in migration file paths
- Check SELinux/AppArmor policies when running in hardened environments
- Monitor mount health for the volume hosting the migration file
When it happens
Trigger: os.Stat(om.filePath) errors with something other than os.IsNotExist: EACCES on a parent directory, ELOOP from symlink cycles, or device-level I/O errors.
Common situations: Wrong ownership/permissions on the migration file's directory; broken symlink loop at the path; failing disk or detached mount; overly restrictive security contexts (SELinux/AppArmor).
Related errors
- failed to create migration directory %q: %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/f4b05b53b5b1b870.
Report an issue: GitHub.