ory/kratos · error
invalid UUID in --start-after
Error message
invalid UUID in --start-after %q
What it means
parseStartAfter validates that the value part of a "key=uuid" --start-after argument is a valid UUID via uuid.FromString. If parsing fails, the underlying UUID parse error is wrapped with "invalid UUID in --start-after <arg>". Raised before any database work, purely from CLI input validation.
Solutions
- Copy the exact UUID from the previous run's resume output or the database id column.
- Verify the value is a 36-character hyphenated UUID (8-4-4-4-12).
- Quote the argument to prevent shell mangling.
Example fix
// before kratos migrate normalize-phone --start-after credentials=abc123 // after kratos migrate normalize-phone --start-after credentials=018f3c2e-3f4a-7b8c-9d0e-1f2a3b4c5d6e
Defensive patterns
Strategy: validation
Validate before calling
re := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)
if !re.MatchString(val) {
return fmt.Errorf("not a UUID: %q", val)
} Type guard
func isUUID(s string) bool {
_, err := uuid.Parse(s)
return err == nil
} Try / catch
null
Prevention
- Copy IDs directly from the resume output or database, never retype them
- Validate UUID shape in wrapper scripts before invoking the CLI
- Confirm the ID source table uses UUID primary keys
When it happens
Trigger: Passing --start-after credentials=not-a-uuid, a truncated UUID, a different ID format (e.g. numeric ID), or an empty value after '='.
Common situations: Hand-copying an ID from logs with typos or truncation, using a non-UUID primary key from a different table, or forgetting the ID entirely after the '=' sign.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- could not parse as UUID
- invalid --start-after format
- expected to get the DSN as an argument, or the…
- expected zero or two args, got
- An error occurred initializing cleanup
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/55a0ece1d8cc9648.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/migrate/normalize_phone_handler.go:134
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) {
result := make(map[string]uuid.UUID)
for _, arg := range args {
key, val, ok := strings.Cut(arg, "=")
if !ok {
return nil, errors.Errorf("invalid --start-after format %q: expected key=uuid (e.g. credentials=<id>)", arg)
}
id, err := uuid.FromString(val)
if err != nil {
return nil, errors.Wrapf(err, "invalid UUID in --start-after %q", arg)
}
result[key] = id
}
return result, nil
}
func printSummary(cmd *cobra.Command, tables []tableConfig, allStats []normalizeStats) {
out := cmd.OutOrStdout()
_, _ = fmt.Fprintln(out)
tw := tabwriter.NewWriter(out, 0, 0, 2, ' ', 0)
_, _ = fmt.Fprintln(tw, "\tSCANNED\tUPDATED\tSKIPPED\tERRORS")
var total normalizeStats
for i, table := range tables {
s := allStats[i]
_, _ = fmt.Fprintf(tw, "%s\t%d\t%d\t%d\t%d\n", table.name, s.scanned, s.updated, s.skipped, s.errors)View on GitHub (pinned to b86338da04)