golang-migrate/migrate · error
not implemented
Error message
not implemented
What it means
VFS.Open intentionally panics with "not implemented": a VFS-backed source driver cannot be constructed from a URL because the underlying virtual filesystem must be supplied as a value. The package docs say to use godoc_vfs.WithInstance instead; Open exists only to satisfy the source.Driver interface.
Source
Thrown at source/godoc_vfs/vfs.go:34
func init() {
source.Register("godoc-vfs", &VFS{})
}
// VFS is an implementation of driver that returns migrations from a virtual
// file system.
type VFS struct {
httpfs.PartialDriver
fs vfs.FileSystem
path string
}
// Open implements the source.Driver interface for VFS.
//
// Calling this function panics, instead use the WithInstance function.
// See the package level documentation for an example.
func (b *VFS) Open(url string) (source.Driver, error) {
panic("not implemented")
}
// WithInstance creates a new driver from a virtual file system.
// If a tree named searchPath exists in the virtual filesystem, WithInstance
// searches for migration files there.
// It defaults to "/".
func WithInstance(fs vfs.FileSystem, searchPath string) (source.Driver, error) {
if searchPath == "" {
searchPath = "/"
}
bn := &VFS{
fs: fs,
path: searchPath,
}
if err := bn.Init(vfs_httpfs.New(fs), searchPath); err != nil {
return nil, errView on GitHub (pinned to 01a9643f14)
Solutions
- Call godoc_vfs.WithInstance(vfsInstance, searchPath) to obtain the source.Driver instead of Open.
- Pass that driver to migrate.NewWithInstance(srcDrv, dbDrv) rather than using URL-based migrate.New.
- If you only need filesystem-based migrations, use the iofs or file source driver with a URL instead.
- Wrap calls in a recover() if you must call arbitrary URL schemes and treat this panic as a config error.
Example fix
// before
m, err := migrate.New("vfs:///migrations", "postgres://...") // panics
// after
src, err := godoc_vfs.WithInstance(myVfs, "/migrations")
m, err := migrate.NewWithInstance("vfs", src, "postgres", dbDrv) Defensive patterns
Strategy: validation
Validate before calling
// never route vfs through URL-based migrate.New; use WithInstance directly
if strings.HasPrefix(url, "vfs") {
return errors.New("vfs source requires godoc_vfs.WithInstance, not migrate.New")
} Try / catch
func safeVfsOpen(v *godoc_vfs.VFS, url string) (src source.Driver, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("vfs.Open panicked (use WithInstance): %v", r)
}
}()
return v.Open(url)
} Prevention
- Always use godoc_vfs.WithInstance(vfs, searchPath) + migrate.NewWithInstance for VFS-backed migrations.
- Never pass vfs-style URLs to migrate.New; only URL-capable drivers support it.
- Read the godoc_vfs package example before integrating; Open is intentionally a panic stub.
- If migrating from v3 code, replace VFS usage with the iofs driver where possible.
When it happens
Trigger: Calling migrate.New/NewWithDatabaseConnection with a URL scheme registered to the VFS source driver, or calling vfsInstance.Open(url) directly on a godoc_vfs.VFS value.
Common situations: Treating the VFS driver like file:// or other URL-based drivers; older code using the deprecated godoc-vfs pattern (v3 and earlier) migrating to newer APIs; copy-pasted migrate.New("vfs://...", dsn) calls.
Related errors
- Register driver is nil
- Register called twice for driver
- Register driver is nil
- Register called twice for driver
- 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/2a15b638de4036da.
Report an issue: GitHub.