ramsey/uuid · error · UnableToBuildUuidException
$e->getMessage()
Error message
$e->getMessage()
What it means
Rfc4122\UuidBuilder::build() wraps its entire body in try/catch (Throwable) and rethrows UnableToBuildUuidException with the original's message, code, and previous-chain. It is the umbrella exception for Uuid::fromString()/fromBytes() and codec decode paths: any fields-validation failure (wrong length, non-RFC variant, invalid version) or constructor failure surfaces as this type carrying the underlying message. Because Uuid::fromString() is lazy, the throw may happen later, when the LazyUuidFromString first unwraps.
Source
Thrown at src/Rfc4122/UuidBuilder.php:108
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_RANDOM => new UuidV4($fields, $this->numberConverter, $codec, $this->timeConverter),
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_HASH_SHA1 => new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter),
Uuid::UUID_TYPE_REORDERED_TIME
/** @phpstan-ignore possiblyImpure.new */
=> new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter),
Uuid::UUID_TYPE_UNIX_TIME
/** @phpstan-ignore possiblyImpure.new */
=> new UuidV7($fields, $this->numberConverter, $codec, $this->unixTimeConverter),
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_CUSTOM => new UuidV8($fields, $this->numberConverter, $codec, $this->timeConverter),
default => throw new UnsupportedOperationException(
'The UUID version in the given fields is not supported by this UUID builder',
),
};
} catch (Throwable $e) {
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
* Proxy method to allow injecting a mock for testing
*
* @pure
*/
protected function buildFields(string $bytes): FieldsInterface
{
/** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
View on GitHub (pinned to da5b521600)
Solutions
- Inspect getPrevious() (and the message) to find the real cause: byte length, variant, or version
- Validate variant and version nibbles before parsing when input is untrusted
- Catch UnableToBuildUuidException at the parse boundary and convert to your domain's invalid-identifier error
Example fix
// before
$uuid = \Ramsey\Uuid\Uuid::fromString($input);
// after
try {
$uuid = \Ramsey\Uuid\Uuid::fromString($input);
} catch (\Ramsey\Uuid\Exception\UnableToBuildUuidException $e) {
$reason = $e->getPrevious()?->getMessage() ?? $e->getMessage();
throw new \InvalidArgumentException("Invalid UUID '{$input}': {$reason}", 0, $e);
} Defensive patterns
Strategy: try-catch
Validate before calling
$hex = strtolower(preg_replace('/^urn:uuid:|[^0-9a-f]/i', '', $input));
if (strlen($hex) !== 32
|| !in_array($hex[16], ['8', '9', 'a', 'b'], true)
|| !in_array(hexdec($hex[12]), range(1, 8), true)) {
throw new InvalidArgumentException('Not a valid RFC 9562 UUID');
}
$uuid = \Ramsey\Uuid\Uuid::fromString($input); Type guard
function isParsableRfc4122Uuid(string $input): bool
{
$hex = strtolower(preg_replace('/^urn:uuid:|[^0-9a-f]/i', '', $input));
return strlen($hex) === 32
&& in_array($hex[16], ['8', '9', 'a', 'b'], true)
&& (hexdec($hex[12]) >= 1 && hexdec($hex[12]) <= 8);
} Try / catch
try {
$uuid = \Ramsey\Uuid\Uuid::fromString($input);
} catch (\Ramsey\Uuid\Exception\UnableToBuildUuidException $e) {
throw new DomainIdentifierInvalid($input, $e->getPrevious()?->getMessage() ?? $e->getMessage(), 0, $e);
} Prevention
- Catch this type wherever UUID strings cross a trust boundary
- Read getPrevious() to distinguish length vs variant vs version failures
- Remember lazy parsing: the throw may occur at first use, not at fromString()
When it happens
Trigger: Uuid::fromString('12345678-1234-4fff-ffff-123456789abc') (bad variant), a version nibble of 0/9-f, or any decode where Fields' constructor rejects the bytes — the visible exception is UnableToBuildUuidException whose message is the wrapped InvalidArgumentException text. Also triggered by custom codecs feeding malformed bytes to the builder.
Common situations: Parsing user-supplied or log-derived UUID strings; accepting IDs from partner systems with non-RFC variants; hex-only validation (Uuid::isValid) passing values that still fail semantic checks.
Related errors
- The byte string received does not conform to the RFC 9562 (f
- The byte string received does not contain a valid RFC 9562 (
- The UUID version in the given fields is not supported by thi
- Could not find a suitable builder for the provided codec and
- Expected version 1 (time-based) UUID
AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21).
Data as JSON: /api/errors/ff6a64ae9d7c9957.
Report an issue: GitHub.