golang-migrate/migrate · error
failed to init driver with path %s: %w
Error message
failed to init driver with path %s: %w
What it means
New wraps any error returned by the iofs driver's Init (the underlying iofs passthrough driver initialization) with context about the path: 'failed to init driver with path %s: %w'. It signals that the given io/fs filesystem plus relative path could not be initialized — most commonly because the path does not exist or is not a directory within the provided fs.FS.
Source
Thrown at source/iofs/iofs.go:24
"errors"
"fmt"
"io"
"io/fs"
"path"
"strconv"
"github.com/golang-migrate/migrate/v4/source"
)
type driver struct {
PartialDriver
}
// New returns a new Driver from io/fs#FS and a relative path.
func New(fsys fs.FS, path string) (source.Driver, error) {
var i driver
if err := i.Init(fsys, path); err != nil {
return nil, fmt.Errorf("failed to init driver with path %s: %w", path, err)
}
return &i, nil
}
// Open is part of source.Driver interface implementation.
// Open cannot be called on the iofs passthrough driver.
func (d *driver) Open(url string) (source.Driver, error) {
return nil, errors.New("open() cannot be called on the iofs passthrough driver")
}
// PartialDriver is a helper service for creating new source drivers working with
// io/fs.FS instances. It implements all source.Driver interface methods
// except for Open(). New driver could embed this struct and add missing Open()
// method.
//
// To prepare PartialDriver for use Init() function.
type PartialDriver struct {
migrations *source.MigrationsView on GitHub (pinned to 01a9643f14)
Solutions
- Verify the path exists inside the fs.FS: fs.Stat(fsys, path) and confirm it is a directory before calling New
- With embed.FS, check the //go:embed pattern — embed 'migrations/*' requires passing 'migrations' as path, while embedding into a migrations package may need "."
- Print available entries with fs.ReadDir(fsys, ".") to see the actual structure and correct the path
- Read the wrapped error (%v on the result) for the root cause, e.g. 'file does not exist'
Example fix
// before //go:embed migrations var fsys embed.FS d, err := iofs.New(fsys, "migrations") // ok if pattern is 'migrations' // if pattern is 'migrations/*.sql' inside package migrations: d, err := iofs.New(fsys, ".")
Defensive patterns
Strategy: validation
Validate before calling
func mustDir(fsys fs.FS, path string) error {
fi, err := fs.Stat(fsys, path)
if err != nil {
return fmt.Errorf("path %q in fs: %w", path, err)
}
if !fi.IsDir() {
return fmt.Errorf("%q is not a directory", path)
}
entries, _ := fs.ReadDir(fsys, path)
if len(entries) == 0 {
return fmt.Errorf("%q contains no migration files", path)
}
return nil
} Try / catch
d, err := iofs.New(fsys, "migrations")
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) {
return fmt.Errorf("bad migrations path %q: %w", perr.Path, err)
}
return err
} Prevention
- Check the //go:embed pattern matches how you reference the path (embedded prefix vs ".")
- Debug embedded layout with fs.ReadDir(fsys, ".") in a unit test
- Pass directories, not files, as the path
- Keep the embed directive and iofs.New path in the same package and tested together
When it happens
Trigger: Calling iofs.New(fsys, path) where fs.Stat(fsys, path) fails or the entry is not a directory — e.g. embedding migrations via embed.FS with an incorrect path prefix (embed paths do not include the 'migrations' directory unless embedded as such).
Common situations: embed.FS path confusion (//go:embed migrations yields entries prefixed 'migrations/' or not, depending on embed pattern); typo'd path; passing a file instead of a directory; using os.DirFS with a wrong root.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- open() cannot be called on the iofs passthrough driver
- no directory
- no directory
- failed to init driver with relative path %q: %w
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/a5cc6bf2aba5a300.
Report an issue: GitHub.