hasura/graphql-engine · error

creating target migrations directory: %w

Error message

creating target migrations directory: %w

What it means

Thrown by UpdateProjectV3 when the CLI cannot create the per-database subdirectory (e.g. <migrations>/<targetDatabase>) while restructuring a config v2 project to the v3 multi-database layout. It wraps the underlying filesystem error (billyfs/afero Mkdir).

Source

Thrown at cli/internal/scripts/update-project-v3.go:173

	// get directory names to move
	migrationDirectoriesToMove, err := getMigrationDirectoryNames(
		opts.Fs,
		opts.MigrationsAbsDirectoryPath,
	)
	if err != nil {
		return errors.E(op, fmt.Errorf("getting list of migrations to move: %w", err))
	}
	// move seed child directories
	// get directory names to move
	seedFilesToMove, err := getSeedFiles(opts.Fs, opts.SeedsAbsDirectoryPath)
	if err != nil {
		return errors.E(op, fmt.Errorf("getting list of seed files to move: %w", err))
	}

	// create a new directory for TargetDatabase
	targetMigrationsDirectoryName := filepath.Join(opts.MigrationsAbsDirectoryPath, targetDatabase)
	if err = opts.Fs.Mkdir(targetMigrationsDirectoryName, 0o755); err != nil {
		return errors.E(op, fmt.Errorf("creating target migrations directory: %w", err))
	}

	// create a new directory for TargetDatabase
	targetSeedsDirectoryName := filepath.Join(opts.SeedsAbsDirectoryPath, targetDatabase)
	if err = opts.Fs.Mkdir(targetSeedsDirectoryName, 0o755); err != nil {
		return errors.E(op, fmt.Errorf("creating target seeds directory: %w", err))
	}

	// move migration directories to target database directory
	if err := copyMigrations(
		opts.Fs,
		migrationDirectoriesToMove,
		opts.MigrationsAbsDirectoryPath,
		targetMigrationsDirectoryName,
	); err != nil {
		return errors.E(op, fmt.Errorf("moving migrations to target database directory: %w", err))
	}
	// move seed directories to target database directory

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Check the underlying error for EEXIST/EROFS/EACCES and fix permissions (chmod/chown) on the migrations directory
  2. If the target directory already exists from a previous partial run, remove it or restore from backup before re-running
  3. Ensure the project directory is writable and not on a read-only mount
  4. Re-run `hasura scripts update-project-v3` once the filesystem issue is fixed

Example fix

# before
hasura scripts update-project-v3
# mkdir /path/to/migrations/postgres: file exists

# after (clean partial state)
rm -rf migrations/postgres seeds/postgres
hasura scripts update-project-v3
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(filepath.Join(migrationsDir, targetDB)); err == nil {
    return fmt.Errorf("target migrations dir already exists; remove it before re-running")
}
if err := os.MkdirAll(migrationsDir, 0o755); err != nil { return err }

Try / catch

if err := scripts.UpdateProjectV3(opts); err != nil {
    if strings.Contains(err.Error(), "creating target migrations directory") {
        // inspect wrapped fs error, fix perms/existing dir, retry after cleanup
    }
}

Prevention

When it happens

Trigger: Running `hasura scripts update-project-v3` when opts.MigrationsAbsDirectoryPath cannot accept a new subdirectory: read-only filesystem, permissions denied, the directory already exists, or a file with the same name exists.

Common situations: Running the update in a directory without write permission, on a mounted/read-only volume, re-running the script after a partial failure that already created the directory, or a corrupted migrations directory.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/86be0cbe602903e4. Report an issue: GitHub.