ramsey/uuid · error · InvalidArgumentException
$bytes string should contain 16 characters.
Error message
$bytes string should contain 16 characters.
What it means
StringCodec::decodeBytes() is the standard binary decode path (used by Uuid::fromBytes()); it builds a UUID from a raw byte string and throws InvalidArgumentException when strlen($bytes) !== 16. The bytes must be the plain 16-octet RFC 4122 representation with no encoding or formatting applied.
Source
Thrown at src/Codec/StringCodec.php:86
/** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
return $uuid->getFields()->getBytes();
}
/**
* @throws InvalidUuidStringException
*
* @inheritDoc
*/
public function decode(string $encodedUuid): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
return $this->builder->build($this, $this->getBytes($encodedUuid));
}
public function decodeBytes(string $bytes): UuidInterface
{
if (strlen($bytes) !== 16) {
throw new InvalidArgumentException('$bytes string should contain 16 characters.');
}
return $this->builder->build($this, $bytes);
}
/**
* Returns the UUID builder
*/
protected function getBuilder(): UuidBuilderInterface
{
return $this->builder;
}
/**
* Returns a byte string of the UUID
*/
protected function getBytes(string $encodedUuid): string
{View on GitHub (pinned to da5b521600)
Solutions
- Convert first: (string) hex2bin($hex) / base64_decode($b64), then check strlen === 16.
- Pre-validate length before fromBytes()/decodeBytes().
- Use BINARY(16) storage so values arrive as exactly 16 raw bytes.
Example fix
// before $uuid = Uuid::fromBytes($hexFromDb); // 32 hex chars -> InvalidArgumentException // after $bytes = (string) hex2bin($hexFromDb); $uuid = Uuid::fromBytes($bytes); // strlen === 16
Defensive patterns
Strategy: validation
Validate before calling
function normalizeTo16Bytes(string $value): string
{
if (strlen($value) === 32 && ctype_xdigit($value)) {
$value = (string) hex2bin($value);
}
if (strlen($value) !== 16) {
throw new InvalidArgumentException(sprintf('expected 16 bytes, got %d', strlen($value)));
}
return $value;
}
$uuid = Uuid::fromBytes(normalizeTo16Bytes($value)); Type guard
function isUuidByteString(string $value): bool
{
return strlen($value) === 16;
} Try / catch
try {
$uuid = Uuid::fromBytes($bytes);
} catch (\Ramsey\Uuid\Exception\InvalidArgumentException $e) {
throw new StoredIdentifierCorruptException($row['id'], $e);
} Prevention
- Use BINARY(16) schema columns so drivers return exactly 16 raw bytes.
- Convert hex/base64 at the boundary, never mid-stack.
- Wrap fromBytes() in one helper with the length assert to keep call sites safe.
- Watch DBAL type mappings - some map BINARY(16) to hex strings by default.
When it happens
Trigger: Uuid::fromBytes($value) where $value is a 32-char hex string, a hyphenated UUID string, base64, or a truncated/oversized binary value.
Common situations: Column stored as CHAR(36)/hex instead of BINARY(16); forgetting hex2bin() after hex transport; ORM or DBAL returning a formatted string for binary columns; substr() bugs cutting bytes.
Related errors
- $bytes string should contain 16 characters.
- Could not find a suitable builder for the provided codec and
- Attempting to decode a non-time-based UUID using OrderedTime
- Invalid UUID string: {encodedUuid}
- Expected version 1 (time-based) UUID
AI-assisted analysis of ramsey/uuid@da5b521600 (2026-08-21).
Data as JSON: /api/errors/540f36424f479e0a.
Report an issue: GitHub.