golang-migrate/migrate · error
open() cannot be called on the iofs passthrough driver
Error message
open() cannot be called on the iofs passthrough driver
What it means
The iofs package wraps an io/fs.FS as a migration source. Its driver's Open method is deliberately unimplemented — instances are created by WithInstance(fsys), not through the URL registry — so any call to Open returns this error. It exists only to complete the source.Driver interface.
Source
Thrown at source/iofs/iofs.go:32
)
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.Migrations
fsys fs.FS
path string
}
// Init prepares not initialized IoFS instance to read migrations from a
// io/fs#FS instance and a relative path.
func (d *PartialDriver) Init(fsys fs.FS, path string) error {
entries, err := fs.ReadDir(fsys, path)View on GitHub (pinned to 01a9643f14)
Solutions
- Use iofs.WithInstance(fsys) (e.g. with an embed.FS) and pass the result via migrate.NewWithSourceInstance("iofs", d, databaseURL).
- When embedding PartialDriver in a custom driver, override Open with a real constructor that returns your driver for valid URLs.
- Do not register the passthrough driver in the URL scheme registry.
Example fix
// before
m, err := migrate.New("iofs://embedded", dsn)
// after
d, err := iofs.WithInstance(migrationsFS)
m, err := migrate.NewWithSourceInstance("iofs", d, dsn) Defensive patterns
Strategy: validation
Validate before calling
d, err := iofs.WithInstance(embeddedFS)
if err != nil { return err }
m, err := migrate.NewWithSourceInstance("iofs", d, databaseURL) Try / catch
if err != nil && strings.Contains(err.Error(), "iofs passthrough") {
return fmt.Errorf("iofs drivers must be created with iofs.WithInstance, not Open")
} Prevention
- Use iofs.WithInstance + migrate.NewWithSourceInstance for embed.FS migrations instead of URL-based construction.
- Never call Open on drivers built from PartialDriver passthroughs.
- Override Open when embedding PartialDriver in your own driver.
When it happens
Trigger: Calling Open on the driver returned by iofs.WithInstance; registering the iofs driver under a URL scheme and then invoking source.Open("iofs://...").
Common situations: Trying to use embed.FS-based migrations through the URL-based migrate.New API instead of migrate.NewWithSourceInstance; wrapping the passthrough driver in another driver and delegating Open to it.
Related errors
- open() cannot be called on the httpfs passthrough driver
- source driver: invalid URL scheme
- source driver: unknown driver '%s' (forgotten import?)
- failed to init driver with path %s: %w
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/e533434598cb93fb.
Report an issue: GitHub.