ory/kratos · error
migrations have not yet been fully applied
Error message
migrations have not yet been fully applied
What it means
During the service bootstrap pipeline (registry_default.go), a boot check queries the persister's MigrationStatus and, if status.HasPending() is true, refuses to continue with this error. It is a safety gate: the schema is not at the expected migration version, so the service would misbehave against a partially migrated database.
Solutions
- Run the migration CLI against the configured DSN: 'kratos migrate sql -e DSN up' (or apply the SQL files with your migration tool).
- Verify the DSN used for migration matches the DSN the server uses, so you are migrating the right database.
- Check 'kratos migrate status -e DSN' to list pending migrations before and after applying.
- If the schema is intentionally behind (e.g. replica), point the service at a fully migrated instance.
Example fix
# before (server started with pending migrations) kratos serve -c kratos.yml # after (apply migrations first, then serve) kratos migrate sql -e DSN up kratos serve -c kratos.yml
Defensive patterns
Strategy: try-catch
Validate before calling
status, err := m.Persister().MigrationStatus(ctx)
if err == nil && status.HasPending() {
return fmt.Errorf("%d pending migrations; run migrations before serving", len(status.Pending()))
} Try / catch
// in startup code
if err := run(); err != nil {
if strings.Contains(err.Error(), "migrations have not yet been fully applied") {
// trigger your migration job, then retry startup
runMigrations(dsn)
return run()
}
return err
} Prevention
- Run migrations as a separate deployment step/job before rolling out the new server version.
- Verify migration status with 'kratos migrate status' in CI before deploying.
- Ensure migration jobs and the server use the exact same DSN.
- Pin service and schema versions together in upgrade runbooks.
When it happens
Trigger: Starting Kratos with a database whose schema migration history has pending migrations — e.g. upgrading to a newer version without running 'kratos migrate sql up', or the migrate command was run partially/against a different database than the one configured in dsn.
Common situations: Version upgrade deployments where migrations were skipped in CI, blue/green setups pointing the new binary at the old schema, and local dev where migrations were applied to one sqlite/postgres instance but the app dsn points at another.
Related errors
- an error occurred initializing migrations
- expected to get the DSN as an argument, or the…
- required config value "dsn" was not set
- could not read schema file
- could not decode schema file
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/795d1be45c9abacc.
Report an issue: GitHub.
Appendix: source
Thrown at driver/registry_default.go:300
func (m *RegistryDefault) HealthHandler(_ context.Context) *healthx.Handler {
if m.healthxHandler == nil {
m.healthxHandler = healthx.NewHandler(m.Writer(), config.Version,
healthx.ReadyCheckers{
"database": func(r *http.Request) error {
return m.PingContext(r.Context())
},
"migrations": func(r *http.Request) error {
if m.migrationStatus != nil && !m.migrationStatus.HasPending() {
return nil
}
status, err := m.Persister().MigrationStatus(r.Context())
if err != nil {
return err
}
if status.HasPending() {
return errors.Errorf("migrations have not yet been fully applied")
}
m.migrationStatus = status
return nil
},
})
}
return m.healthxHandler
}
func (m *RegistryDefault) WithCSRFHandler(c nosurf.Handler) {
m.nosurf = c
}
func (m *RegistryDefault) CSRFHandler() nosurf.Handler {
if m.nosurf == nil {
panic("csrf handler is not set")View on GitHub (pinned to b86338da04)