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
- Set the Runner field when building the Migration, e.g. the standard SQL file executor from the library
- Use the library's migration factory/loader helpers instead of hand-assembling Migration structs
- 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
- Use the library's standard file loader instead of hand-building Migration structs
- Set Runner at every construction site; keep a constructor helper that requires it
- Re-check Migration struct fields after upgrading the library version
- Add a unit test that runs Valid() over all registered migrations
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
- cookiex: purpose must be non-empty and must not contain a pi
- cookiex: at least one secret is required
- file loader disabled
- http(s) loader disabled
- plan must define a DefaultPageToken
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/21f86a1226fe8148.
Report an issue: GitHub.