ramsey/uuid · error · BuilderNotFoundException

Could not find a suitable builder for the provided codec and

Error message

Could not find a suitable builder for the provided codec and fields

What it means

Thrown by FallbackBuilder::build() after it walked its whole builder list and every builder threw UnableToBuildUuidException. FallbackBuilder is a chain-of-responsibility builder (typically holding a BuilderCollection of DegradedUuidBuilder and Rfc4122UuidBuilder) that codecs call with the raw byte string. In practice the byte string itself was rejected by every builder - most often because it is not exactly 16 bytes (e.g. a 32-character hex string passed instead of raw binary).

Source

Thrown at src/Builder/FallbackBuilder.php:60

     * @return UuidInterface an instance of a UUID object
     *
     * @pure
     */
    public function build(CodecInterface $codec, string $bytes): UuidInterface
    {
        $lastBuilderException = null;

        foreach ($this->builders as $builder) {
            try {
                return $builder->build($codec, $bytes);
            } catch (UnableToBuildUuidException $exception) {
                $lastBuilderException = $exception;

                continue;
            }
        }

        throw new BuilderNotFoundException(
            'Could not find a suitable builder for the provided codec and fields',
            0,
            $lastBuilderException,
        );
    }
}

View on GitHub (pinned to da5b521600)

Solutions

  1. Convert before decoding: $bytes = (string) hex2bin($hex); base64_decode($b64) if the transport is base64 - the result must be exactly 16 bytes.
  2. Validate strlen($bytes) === 16 before calling fromBytes()/decodeBytes() and reject early.
  3. Inspect $e->getPrevious() on the BuilderNotFoundException - it carries the last UnableToBuildUuidException and its reason.
  4. Verify the FallbackBuilder was constructed with a non-empty BuilderCollection containing builders suited to your codec (Rfc4122UuidBuilder / DegradedUuidBuilder).

Example fix

// before
$uuid = $factory->getCodec()->decodeBytes($row['uuid_hex']); // 32 hex chars -> BuilderNotFoundException

// after
$bytes = (string) hex2bin($row['uuid_hex']);
assert(strlen($bytes) === 16);
$uuid = $factory->getCodec()->decodeBytes($bytes);
Defensive patterns

Strategy: validation

Validate before calling

function toUuidBytes(string $raw): string
{
    // Accept raw 16 bytes, or a 32-char hex string, and normalize.
    if (strlen($raw) === 32 && ctype_xdigit($raw)) {
        $raw = (string) hex2bin($raw);
    }
    if (strlen($raw) !== 16) {
        throw new InvalidArgumentException('UUID byte string must be exactly 16 bytes');
    }

    return $raw;
}

$uuid = $codec->decodeBytes(toUuidBytes($value));

Try / catch

try {
    $uuid = $codec->decodeBytes($bytes);
} catch (\Ramsey\Uuid\Exception\BuilderNotFoundException $e) {
    $reason = $e->getPrevious(); // last UnableToBuildUuidException
    // Treat as invalid stored data: log $reason, quarantine the row.
    throw new StoredIdentifierCorruptException($row['id'], $reason);
}

Prevention

When it happens

Trigger: A UUID factory whose builder is a FallbackBuilder, then a decode path is fed bad bytes: $codec->decodeBytes($hexString) with a 32-char hex string, Uuid::fromBytes('') or truncated/oversized binary, or data read from a store that hex- or base64-encodes byte columns.

Common situations: Forgetting hex2bin() before fromBytes()/decodeBytes(); database abstraction returning hex for BINARY(16) columns (or the column actually being CHAR(32)/CHAR(36)); cache or queue round-trips that mangle binary payloads; empty input coerced to an empty string.

Related errors


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