ramsey/uuid · error · InvalidUuidStringException

Invalid UUID string: {encodedUuid}

Error message

Invalid UUID string: {encodedUuid}

What it means

StringCodec::getBytes() powers Uuid::fromString() and $codec->decode(): it strips 'urn:uuid:'/'UUID:' prefixes, braces and dashes, re-groups the remainder into five components, and validates the reassembled form with Uuid::isValid(). When validation fails it throws InvalidUuidStringException with the offending input in the message.

Source

Thrown at src/Codec/StringCodec.php:116

    }

    /**
     * Returns a byte string of the UUID
     */
    protected function getBytes(string $encodedUuid): string
    {
        $parsedUuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}', '-'], '', $encodedUuid);

        $components = [
            substr($parsedUuid, 0, 8),
            substr($parsedUuid, 8, 4),
            substr($parsedUuid, 12, 4),
            substr($parsedUuid, 16, 4),
            substr($parsedUuid, 20),
        ];

        if (!Uuid::isValid(implode('-', $components))) {
            throw new InvalidUuidStringException('Invalid UUID string: ' . $encodedUuid);
        }

        return (string) hex2bin($parsedUuid);
    }
}

View on GitHub (pinned to da5b521600)

Solutions

  1. Validate first: if (!Uuid::isValid(trim($value))) { reject } - isValid accepts braces, URN and dashes exactly like fromString.
  2. Normalize input: trim whitespace/newlines before parsing.
  3. Reject bad IDs at the API boundary (HTTP 400 / domain error) instead of letting the exception escape.
  4. Confirm the source wrote a full 32-hex-digit value (column wide enough, no partial reads).

Example fix

// before
$uuid = Uuid::fromString($request->query('id')); // may throw InvalidUuidStringException

// after
$value = trim((string) $request->query('id'));
if (!Uuid::isValid($value)) {
    throw new NotFoundHttpException('invalid identifier');
}
$uuid = Uuid::fromString($value);
Defensive patterns

Strategy: validation

Validate before calling

$value = trim((string) $input);
if (!\Ramsey\Uuid\Uuid::isValid($value)) {
    throw new InvalidArgumentException(sprintf('not a valid UUID string: %s', $value));
}
$uuid = Uuid::fromString($value);

Type guard

function isParsableUuidString(mixed $value): bool
{
    return is_string($value) && Uuid::isValid(trim($value));
}

Try / catch

try {
    $uuid = Uuid::fromString($value);
} catch (\Ramsey\Uuid\Exception\InvalidUuidStringException $e) {
    // invalid external identifier - respond 404/400 rather than a 500
    throw new NotFoundHttpException('unknown identifier');
}

Prevention

When it happens

Trigger: Uuid::fromString() with an empty string, non-hex characters (g-z, punctuation), the wrong number of hex digits after stripping, leading/trailing whitespace or newlines, a ULID or other non-UUID identifier, or a value truncated by copy/paste or a char(32)/char(36) column.

Common situations: Unvalidated user/API input reaching fromString(); CSV/file lines with trailing newline; identifiers truncated by database column width; null coerced to ''; passing a 32-hex COMB string with an odd character.

Related errors


AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21). Data as JSON: /api/errors/daded6c8f5b0445d. Report an issue: GitHub.