ory/kratos · error
normalizing
Error message
normalizing %s
What it means
NormalizePhoneNumbers iterates over tables needing phone normalization (identity_credentials etc.) and calls normalizeTable per table. If batch normalization of a table fails at any step, the error is wrapped with "normalizing <table>". It identifies which table's processing failed; the underlying cause carries the real failure.
Solutions
- Check the wrapped cause to see whether it was the query or the update phase.
- Re-run the command; it is resumable via --start-after credentials=<last-id>.
- Run with --dry-run first to detect data problems before writing.
- Resolve database locks/connectivity issues, then retry the affected table.
Example fix
// before: failed mid-run kratos migrate normalize-phone // after: resume after the last processed ID kratos migrate normalize-phone --start-after credentials=018f3c2e-...
Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
if err := normalizePhoneNumbers(cmd, args); err != nil {
if strings.HasPrefix(err.Error(), "normalizing ") {
// table-level failure: log table name and resume later
log.Printf("normalization failed: %v; resume with --start-after", err)
return cmdx.FailSilently(cmd)
}
return err
} Prevention
- Always run with --dry-run first on production data
- Use --start-after to resume interrupted runs instead of restarting
- Run during low-traffic windows to avoid row locks and contention
When it happens
Trigger: Running the phone-normalization migration command when normalizeTable returns an error for a given table — e.g. failed row query, failed update during a batch, or a write conflict mid-run.
Common situations: Database connection dropped mid-batch, a concurrent process locking rows, or resuming an interrupted run with a stale --start-after ID pointing past deleted rows.
Related errors
- querying
- expected to get the DSN as an argument, or the…
- required config value "dsn" was not set
- An error occurred initializing cleanup
- An error occurred while cleaning up expired data
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/dfb9e762005e2035.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/migrate/normalize_phone_handler.go:107
ORDER BY id ASC LIMIT ?`,
updateQuery: `UPDATE identity_recovery_addresses SET value = ?, updated_at = ? WHERE id = ? AND value = ?`,
},
}
startAfterMap, err := parseStartAfter(flagx.MustGetStringSlice(cmd, "start-after"))
if err != nil {
return err
}
allStats := make([]normalizeStats, len(tables))
for i, table := range tables {
startAfter := startAfterMap[table.key]
if startAfter != uuid.Nil {
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "%s: resuming after ID %s\n", table.name, startAfter)
}
stats, err := normalizeTable(conn, batchSize, batchDelay, startAfter, dryRun, cmd, table)
if err != nil {
return errors.Wrapf(err, "normalizing %s", table.name)
}
allStats[i] = stats
}
printSummary(cmd, tables, allStats)
return nil
}
type tableConfig struct {
key string
name string
selectQuery string
updateQuery string
}
// parseStartAfter parses --start-after flags of the form "key=uuid".
func parseStartAfter(args []string) (map[string]uuid.UUID, error) {View on GitHub (pinned to b86338da04)