pocketbase/pocketbase · error
failed to save migration file %q: %v
Error message
failed to save migration file %q: %v
What it means
Returned by migratecmd's migrateCreateHandler (plugins/migratecmd/migratecmd.go:186) when os.WriteFile fails to persist the newly generated migration file at resultFilePath. The migrations dir was just ensured via MkdirAll, so failures are file-level: permission denied, disk full, existing read-only file with the same timestamped name, or invalid path characters on the host OS.
Source
Thrown at plugins/migratecmd/migratecmd.go:186
var templateErr error
if p.config.TemplateLang == TemplateLangJS {
template, templateErr = p.jsBlankTemplate()
} else {
template, templateErr = p.goBlankTemplate()
}
if templateErr != nil {
return "", fmt.Errorf("failed to resolve create template: %v", templateErr)
}
}
// ensure that the migrations dir exist
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return "", err
}
// save the migration file
if err := os.WriteFile(resultFilePath, []byte(template), 0644); err != nil {
return "", fmt.Errorf("failed to save migration file %q: %v", resultFilePath, err)
}
if interactive {
fmt.Printf("Successfully created file %q\n", resultFilePath)
}
return filename, nil
}
func (p *plugin) migrateCollectionsHandler(args []string, interactive bool) (string, error) {
createArgs := []string{"collections_snapshot"}
createArgs = append(createArgs, args...)
collections := []*core.Collection{}
if err := p.app.CollectionQuery().OrderBy("created ASC").All(&collections); err != nil {
return "", fmt.Errorf("failed to fetch migrations list: %v", err)
}
View on GitHub (pinned to 5d217ddb50)
Solutions
- Retry after fixing ownership/permissions of the migrations dir: `chown -R $(id -u) pb_migrations && chmod -R u+rwX pb_migrations`.
- Free disk space or raise the container writable-layer limit.
- Remove or chmod the pre-existing read-only file that collides with the generated name.
- Run the CLI as the same user that owns the application files, never mix sudo and non-sudo invocations.
Example fix
# before: root-owned migration files from a sudo run $ sudo ./pocketbase migrate create add_posts $ ./pocketbase migrate create add_users # fails to write # after: unify ownership, then run unprivileged $ sudo chown -R $USER pb_migrations $ ./pocketbase migrate create add_users
Defensive patterns
Strategy: validation
Validate before calling
// Verify the target file path is writable before invoking migrate create.
func migrationPathWritable(dir, filename string) bool {
target := filepath.Join(dir, filename)
if info, err := os.Stat(target); err == nil && info.Mode().Perm()&0o200 == 0 {
return false // existing read-only collision
}
return dirWritable(dir) // reuse the CreateTemp probe from error 228
} Prevention
- Always run the pocketbase CLI as the user owning pb_migrations (no sudo for one run, plain user the next).
- Add a pre-command `chmod -R u+rwX pb_migrations` to deployment scripts.
- Keep collection/migration names free of characters invalid on Windows (':', '?', '*').
- Watch disk space in CI containers where migrations are generated.
When it happens
Trigger: Executing `./pocketbase migrate create` or `migrate collections` when the process cannot write into the migrations dir; a same-named file already exists and is read-only; disk exhaustion; running as non-root against a root-owned pb_migrations.
Common situations: Developers running the CLI with sudo once (files become root-owned) and later without; CI containers with size-limited writable layers; filenames containing characters rejected by Windows (e.g. ':' from a clock-formatted name).
Related errors
- failed to create migration dir: %w
- registerHooks: %w
- failed to save automigrate file: %w
- failed to resolve create template: %v
- failed to fetch migrations list: %v
AI-assisted analysis of pocketbase/pocketbase@5d217ddb50 (2026-08-15).
Data as JSON: /api/errors/dc65b61b3f0f31b5.
Report an issue: GitHub.