ory/hydra · error

no runner defined for %s

Error message

no runner defined for %s

What it means

Migration.Valid() asserts that every Migration carries a non-nil Runner function. A Migration struct built with Runner == nil fails validation with 'no runner defined for %s', where %s is the migration file path. This is a programmer/config error, not a runtime database issue.

Source

Thrown at oryx/popx/migration_info.go:40

	Name string
	// Direction of the migration (up|down)
	Direction string
	// Type of migration (sql|go)
	Type string
	// DB type (all|postgres|mysql...)
	DBType string
	// Runner function to run/execute the migration. Will be wrapped in a
	// database transaction. Mutually exclusive with RunnerNoTx
	Runner func(Migration, *pop.Connection) error
	// Content is the raw content of the migration file
	Content string
	// Autocommit indicates whether the migration should be run in autocommit mode
	Autocommit bool
}

func (m Migration) Valid() error {
	if m.Runner == nil {
		return errors.Errorf("no runner defined for %s", m.Path)
	}

	return nil
}

// Migrations is a collection of Migration
type Migrations []Migration

func (mfs Migrations) Len() int           { return len(mfs) }
func (mfs Migrations) Less(i, j int) bool { return compareMigration(mfs[i], mfs[j]) < 0 }
func (mfs Migrations) Swap(i, j int)      { mfs[i], mfs[j] = mfs[j], mfs[i] }

func compareMigration(a, b Migration) int {
	if a.Version != b.Version {
		return strings.Compare(a.Version, b.Version)
	}
	// Force "all" to be greater.
	if a.DBType == "all" && b.DBType != "all" {

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Set the Runner field when building the Migration, e.g. the standard SQL file executor from the library
  2. Use the library's migration factory/loader helpers instead of hand-assembling Migration structs
  3. Check the library version's Migration struct fields and update custom construction code

Example fix

// before
m := popx.Migration{Version: "20240101120000", Path: mf.Path}
// after
m := popx.Migration{Version: "20240101120000", Path: mf.Path, Runner: popx.NewSQLRunner(mf)}
Defensive patterns

Strategy: validation

Validate before calling

// Validate custom-built migrations before handing them to NewMigrationBox
for i := range migrations {
  if migrations[i].Runner == nil {
    return fmt.Errorf("migration %s has nil Runner", migrations[i].Path)
  }
  if err := migrations[i].Valid(); err != nil { return err }
}

Prevention

When it happens

Trigger: Constructing a Migration value programmatically (or via a custom loader) that omits the Runner field, then calling Valid() — which check() invokes for every up migration during NewMigrationBox.

Common situations: Custom migration loaders populating Version/Path but forgetting Runner; copying Migration construction code from older library versions where Runner didn't exist; SQL migrations registered without the standard file runner.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/21f86a1226fe8148. Report an issue: GitHub.