ramsey/uuid · error · ValueError

%s(): Argument #1 ($data) is invalid

Error message

%s(): Argument #1 ($data) is invalid

What it means

UUID fields classes use SerializableFieldsTrait; __unserialize() expects exactly the array layout __serialize() emits - a 'bytes' key holding the 16-byte string. A ValueError ('SerializableFieldsTrait...::__unserialize(): Argument #1 ($data) is invalid') means the payload array lacks that key, i.e. the serialized representation is corrupt or hand-built.

Source

Thrown at src/Fields/SerializableFieldsTrait.php:77

     * @param string $data The serialized string representation of the object
     */
    public function unserialize(string $data): void
    {
        if (strlen($data) === 16) {
            $this->__construct($data);
        } else {
            $this->__construct(base64_decode($data));
        }
    }

    /**
     * @param array{bytes?: string} $data
     */
    public function __unserialize(array $data): void
    {
        // @codeCoverageIgnoreStart
        if (!isset($data['bytes'])) {
            throw new ValueError(sprintf('%s(): Argument #1 ($data) is invalid', __METHOD__));
        }
        // @codeCoverageIgnoreEnd

        $this->unserialize($data['bytes']);
    }
}

View on GitHub (pinned to da5b521600)

Solutions

  1. Treat the entry as poison: delete/regenerate the cached serialized UUIDs instead of repairing payloads.
  2. Wrap unserialize() in try/catch (ValueError / Throwable) and fall back to a cache miss + regenerate.
  3. Store UUIDs in caches as canonical strings and re-parse with Uuid::fromString(), not as serialized objects.

Example fix

// before
$fields = unserialize($cachedSerializedFields); // ValueError if payload lost 'bytes'

// after
try {
    $fields = unserialize($cachedSerializedFields);
} catch (\Throwable $e) {
    $cache->delete($key);
    $fields = null; // regenerate from the UUID string
}
Defensive patterns

Strategy: try-catch

Validate before calling

$payload = @unserialize($cached, ['allowed_classes' => true]);
if (!is_array($payload) || !isset($payload['bytes'])) {
    // missing 'bytes' key: treat as corrupt, regenerate
    $payload = null;
}

Type guard

function isSerializableFieldsPayload(mixed $data): bool
{
    return is_array($data) && isset($data['bytes']) && is_string($data['bytes']);
}

Try / catch

try {
    $object = unserialize($cached);
} catch (\ValueError $e) {
    $cache->delete($key); // poison entry
    $object = null;       // regenerate from source of truth
}

Prevention

When it happens

Trigger: unserialize() over a truncated or rewritten serialization of a Fields object (or a Uuid that embeds fields) whose array no longer contains 'bytes'; manually constructing the payload array without the 'bytes' key.

Common situations: Redis/Memcached/file-cache entries corrupted by partial writes, eviction bugs, or version skew across ramsey/uuid upgrades; session data truncated by storage limits; custom serializers or object mappers mangling the internal array.

Related errors


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