{"record":{"id":"a59e8ff236f55b16","repo":"ory/hydra","slug":"problem-with-migration","errorCode":null,"errorMessage":"problem with migration","messagePattern":"problem with migration","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/popx/migrator.go","lineNumber":633,"sourceCode":"\n\tdialect := mb.c.Dialect.Name()\n\tfallbacks := mb.migrationFallbacks()\n\tmigrationsUp := mb.migrationsUp.sortAndFilter(dialect, fallbacks...)\n\n\tif len(migrationsUp) == 0 {\n\t\treturn nil, errors.Errorf(\"unable to find any migrations for dialect: %s\", dialect)\n\t}\n\n\talreadyApplied := make([]string, 0, len(migrationsUp))\n\terr := con.RawQuery(fmt.Sprintf(\"SELECT version FROM %s\", sanitizedMigrationTableName(con))).All(&alreadyApplied)\n\tif err != nil {\n\t\tif errIsTableNotFound(err) {\n\t\t\t// This means that no migrations have been applied and we need to apply all of them first!\n\t\t\t//\n\t\t\t// It also means that we can ignore this state and act as if no migrations have been applied yet.\n\t\t} else {\n\t\t\t// On any other error, we fail.\n\t\t\treturn nil, errors.Wrap(err, \"problem with migration\")\n\t\t}\n\t}\n\n\tstatuses := make(MigrationStatuses, len(migrationsUp))\n\tfor k, mf := range migrationsUp {\n\t\tdownContent := \"-- error: no down migration defined for this migration\"\n\t\tif mDown := mb.migrationsDown.find(mf.Version, dialect, fallbacks...); mDown != nil {\n\t\t\tdownContent = mDown.Content\n\t\t}\n\t\tstatuses[k] = MigrationStatus{\n\t\t\tState:       Pending,\n\t\t\tVersion:     mf.Version,\n\t\t\tName:        mf.Name,\n\t\t\tContentUp:   mf.Content,\n\t\t\tContentDown: downContent,\n\t\t}\n\n\t\tif slices.ContainsFunc(alreadyApplied, func(applied string) bool {","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/popx/migrator.go#L615-L651","documentation":"Status() queries all applied versions with 'SELECT version FROM <schema_migration table>'. If that query fails with anything other than 'table not found' (which is treated as 'nothing applied yet'), the error is unexpected and Status gives up, wrapping it with 'problem with migration'. It guards the happy path: table-not-found is fine on a fresh database, any other failure indicates a real database problem reading the migration bookkeeping table.","triggerScenarios":"Calling MigrationBox.Status(ctx) when the SELECT version FROM <migration_table> query fails with an error that does not match errIsTableNotFound's patterns ('no such table:', MySQL Error 1146, SQLSTATE 42P01) — e.g. permission denied, connection failure, query timeout/cancellation, or a corrupted migration table with an unexpected schema.","commonSituations":"The DB user can connect but lacks SELECT privilege on the schema_migration table; the database was restarted or the connection pool broke mid-query; a context timeout cancels the query; the table exists but was manually altered so 'version' column is missing; TLS/network flakiness in CI.","solutions":["Inspect the wrapped inner error for the actual database cause.","Verify the database user has SELECT privilege on the schema_migration table.","Confirm the schema_migration table still has its 'version' column (revert manual modifications or restore from a backup).","Check connectivity/pool health and ensure the context passed to Status is not cancelled or near its deadline.","If the table truly does not exist but the error message differs (unsupported driver error text), run CreateSchemaMigrations first to bootstrap it."],"exampleFix":"// before: user lacks SELECT on bookkeeping table\nGRANT SELECT ON schema_migration TO app_user;\n// after: Status query succeeds\nstatuses, err := mb.Status(ctx)","handlingStrategy":"try-catch","validationCode":"// verify SELECT access on the bookkeeping table before calling Status\nif err := c.RawQuery(\"SELECT 1 FROM schema_migration LIMIT 1\").Exec(); err != nil && !isTableNotFound(err) {\n    return fmt.Errorf(\"cannot read schema_migration: %w — check privileges/connectivity\", err)\n}","typeGuard":null,"tryCatchPattern":"statuses, err := mb.Status(ctx)\nif err != nil && strings.Contains(err.Error(), \"problem with migration\") {\n    // unexpected DB failure reading migration table: log cause, check privileges/connections\n    log.Printf(\"migration status read failed: %+v\", err)\n    return err\n}","preventionTips":["Grant SELECT on the schema_migration table to the application user.","Do not manually alter the schema_migration table or its version column.","Ensure the context passed to Status has adequate deadline headroom.","Keep connection pool health checks enabled so broken connections are retried upstream."],"tags":["database","migration","sql","permissions"],"backgroundTag":"migration-status-query-failed","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}