{"record":{"id":"dfb9e762005e2035","repo":"ory/kratos","slug":"normalizing-s","errorCode":null,"errorMessage":"normalizing %s","messagePattern":"normalizing (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/migrate/normalize_phone_handler.go","lineNumber":107,"sourceCode":"\t\t\tORDER BY id ASC LIMIT ?`,\n\t\t\tupdateQuery: `UPDATE identity_recovery_addresses SET value = ?, updated_at = ? WHERE id = ? AND value = ?`,\n\t\t},\n\t}\n\n\tstartAfterMap, err := parseStartAfter(flagx.MustGetStringSlice(cmd, \"start-after\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tallStats := make([]normalizeStats, len(tables))\n\tfor i, table := range tables {\n\t\tstartAfter := startAfterMap[table.key]\n\t\tif startAfter != uuid.Nil {\n\t\t\t_, _ = fmt.Fprintf(cmd.ErrOrStderr(), \"%s: resuming after ID %s\\n\", table.name, startAfter)\n\t\t}\n\t\tstats, err := normalizeTable(conn, batchSize, batchDelay, startAfter, dryRun, cmd, table)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"normalizing %s\", table.name)\n\t\t}\n\t\tallStats[i] = stats\n\t}\n\n\tprintSummary(cmd, tables, allStats)\n\n\treturn nil\n}\n\ntype tableConfig struct {\n\tkey         string\n\tname        string\n\tselectQuery string\n\tupdateQuery string\n}\n\n// parseStartAfter parses --start-after flags of the form \"key=uuid\".\nfunc parseStartAfter(args []string) (map[string]uuid.UUID, error) {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/cmd/migrate/normalize_phone_handler.go#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: failed mid-run\nkratos migrate normalize-phone\n// after: resume after the last processed ID\nkratos migrate normalize-phone --start-after credentials=018f3c2e-... ","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"if err := normalizePhoneNumbers(cmd, args); err != nil {\n    if strings.HasPrefix(err.Error(), \"normalizing \") {\n        // table-level failure: log table name and resume later\n        log.Printf(\"normalization failed: %v; resume with --start-after\", err)\n        return cmdx.FailSilently(cmd)\n    }\n    return err\n}","preventionTips":["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"],"tags":["database","migration","batch-processing","phone-normalization"],"backgroundTag":"database-write-failed","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}