ory/kratos · error

could not parse as UUID

Error message

could not parse %q as UUID: %w

What it means

This error is raised when parsing a session identifier string into a UUID fails (uuid.FromString). The session handler accepts a list of raw session ID strings and must convert each into a strongly-typed uuid.UUID before further processing. It wraps the underlying uuid library error so the offending raw value is visible in the message.

Solutions

  1. Print the offending value from the message (%q) and correct it to a valid UUID session identifier.
  2. Validate IDs before submission, e.g. with uuid.FromString or a regex for the 8-4-4-4-12 hex format.
  3. Trim whitespace and strip quotes/braces from the value before passing it.
  4. If you only have an identity or user ID, look up the associated session IDs first via the identities API.

Example fix

// before
mycli sessions get --sessions 12345
// after
mycli sessions get --sessions 5ba2e8a9-3f2e-4a1c-9d0e-7b6c5a4d3e2f
Defensive patterns

Strategy: validation

Validate before calling

import "github.com/gofrs/uuid"
for _, s := range ids {
    if _, err := uuid.FromString(strings.TrimSpace(s)); err != nil {
        return fmt.Errorf("invalid session ID %q: %w", s, err)
    }
}

Prevention

When it happens

Trigger: Calling the session list/management API path where session IDs (from flags, request parameters, or the wildcard-rejection loop in session/handler.go:1403) include a string that is not a valid RFC 4122 UUID, e.g. an email address, numeric ID, or truncated identifier.

Common situations: Developers pass session tokens, external user IDs, or database serial numbers instead of UUID session IDs; copy-pasting IDs with whitespace, quotes, or trailing newlines; older clients using non-UUID identifiers.

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


AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07). Data as JSON: /api/errors/f72654b00bb99d08. Report an issue: GitHub.

Appendix: source

Thrown at session/handler.go:1403

// parseManageSessionsIDs interprets a manage-sessions filter array as a list
// of explicit UUIDs and rejects any input containing the wildcard token.
// Callers that accept the wildcard must use parseManageSessionsIDsOrWildcard.
func parseManageSessionsIDs(raw []string) ([]uuid.UUID, error) {
	if len(raw) == 0 {
		return nil, errors.New("array must not be empty")
	}
	if len(raw) > ManageSessionsMaxIDs {
		return nil, fmt.Errorf("at most %d IDs may be provided per call", ManageSessionsMaxIDs)
	}
	ids := make([]uuid.UUID, 0, len(raw))
	for _, s := range raw {
		if s == ManageSessionsAllToken {
			return nil, errors.New("the wildcard '*' is not accepted here")
		}
		id, err := uuid.FromString(s)
		if err != nil {
			return nil, fmt.Errorf("could not parse %q as UUID: %w", s, err)
		}
		ids = append(ids, id)
	}
	return ids, nil
}

// wildcardBatch runs a single chunked bulk-session operation and packages the
// row count plus a `more` flag for the response. `more` is true when the call
// reached the per-call batch limit, signaling that the caller should re-issue
// the request to drain the rest.
//
// When the row count is an exact multiple of the batch size, `more` is set
// even though no rows are left; the caller will issue one extra request that
// returns `{processed: 0, more: false}`. This is intentional — distinguishing
// "exactly batch-size" from "batch-size and more" would cost an extra DB
// query on every call to save one round-trip in a rare edge case.
func wildcardBatch(ctx context.Context, op func(context.Context, int) (int, error)) (*ManageSessionsResponse, error) {
	n, err := op(ctx, manageSessionsWildcardBatchSize)

View on GitHub (pinned to b86338da04)