golang-migrate/migrate · error

failed to init driver with relative path %q: %w

Error message

failed to init driver with relative path %q: %w

What it means

golang-migrate's pkger source driver wraps a go-pkger embedded filesystem. Open(url) parses the URL and calls Init on the driver with the URL's path; if Init fails (e.g. the path does not exist inside the embedded pkger filesystem), the underlying error is wrapped as "failed to init driver with relative path %q: %w".

Source

Thrown at source/pkger/pkger.go:45

// migrations must be added to the global pkger.Pkger instance by calling
// pkger.Apply. Refer to Pkger documentation for more information.
func (p *Pkger) Open(url string) (source.Driver, error) {
	u, err := stdurl.Parse(url)
	if err != nil {
		return nil, err
	}

	// wrap pkger to implement http.FileSystem.
	fs := fsFunc(func(name string) (http.File, error) {
		f, err := pkger.Open(name)
		if err != nil {
			return nil, err
		}
		return f.(http.File), nil
	})

	if err := p.Init(fs, u.Path); err != nil {
		return nil, fmt.Errorf("failed to init driver with relative path %q: %w", u.Path, err)
	}

	return p, nil
}

// WithInstance returns a source.Driver that is backed by an instance of
// pkging.Pkger. The relative location of migrations is indicated by path. The
// path must exist on the pkging.Pkger instance for the driver to initialize
// successfully.
func WithInstance(instance pkging.Pkger, path string) (source.Driver, error) {
	if instance == nil {
		return nil, fmt.Errorf("expected instance of pkging.Pkger")
	}

	// wrap pkger to implement http.FileSystem.
	fs := fsFunc(func(name string) (http.File, error) {
		f, err := instance.Open(name)
		if err != nil {

View on GitHub (pinned to 01a9643f14)

Solutions

  1. Regenerate the pkger bundle (pkger -include /migrations) so the path exists in the embedded filesystem, then rebuild.
  2. Verify the path component of the pkger URL exactly matches an existing directory in the pkger instance (case-sensitive).
  3. Inspect the wrapped error (errors.Unwrap / %w chain) from p.Init to see the root cause (e.g. file does not exist).
  4. Ensure migrations were embedded before running tests in CI; pkger assets are only present after generation.

Example fix

// before (URL points to missing dir)
m, err := migrate.New("pkger:///migrats", "postgres://...")
// after
go run github.com/markbates/pkger/cmd/pkger -include /migrations
m, err := migrate.New("pkger:///migrations", "postgres://...")
Defensive patterns

Strategy: validation

Validate before calling

// before building the URL, confirm the embedded path exists
f, err := pkger.Open("/migrations")
if err != nil {
	return fmt.Errorf("pkger path /migrations not embedded: %w", err)
}
f.Close()
m, err := migrate.New("pkger:///migrations", dsn)

Try / catch

if err != nil {
	if strings.Contains(err.Error(), "failed to init driver with relative path") {
		// inspect errors.Unwrap(err) for the root cause; fix embed path and rebuild
	}
	return err
}

Prevention

When it happens

Trigger: Calling migrate.New with a pkger:// URL whose embedded path does not exist inside the go-pkger package, e.g. source/pkger!migrations not included at build time, or a typo'd subdirectory in the URL path.

Common situations: Using pkger to embed migrations but forgetting to run the pkger tool before building, migrations living in a directory different from the URL path, or renaming the migrations folder without updating the URL.

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/54b195439f28c166. Report an issue: GitHub.