ramsey/uuid · error · DceSecurityException

Unable to get a user identifier using the system DCE Securit

Error message

Unable to get a user identifier using the system DCE Security provider; please provide a custom identifier or use a different provider

What it means

SystemDceSecurityProvider backs Uuid::uuid2() (DCE security, version 2). On first use it caches the POSIX UID via getSystemUid(): shell_exec('id -u') on Unix, or whoami SID parsing on Windows. If that lookup returns an empty string — shell_exec disabled, command missing, or Windows output unparsable — getUid() throws DceSecurityException telling you to supply an identifier yourself.

Source

Thrown at src/Provider/Dce/SystemDceSecurityProvider.php:56

     * @throws DceSecurityException if unable to get a user identifier
     *
     * @inheritDoc
     */
    public function getUid(): IntegerObject
    {
        /** @var IntegerObject | int | float | string | null $uid */
        static $uid = null;

        if ($uid instanceof IntegerObject) {
            return $uid;
        }

        if ($uid === null) {
            $uid = $this->getSystemUid();
        }

        if ($uid === '') {
            throw new DceSecurityException(
                'Unable to get a user identifier using the system DCE Security provider; please provide a custom '
                . 'identifier or use a different provider',
            );
        }

        $uid = new IntegerObject($uid);

        return $uid;
    }

    /**
     * @throws DceSecurityException if unable to get a group identifier
     *
     * @inheritDoc
     */
    public function getGid(): IntegerObject
    {
        /** @var IntegerObject | int | float | string | null $gid */

View on GitHub (pinned to da5b521600)

Solutions

  1. Pass an explicit identifier: Uuid::uuid2(Uuid::DCE_DOMAIN_PERSON, 1000) (and domain), avoiding the system lookup entirely
  2. Provide a custom DceSecurityProviderInterface implementation to UuidFactory and call $factory->uuid2()
  3. Ask your host to enable shell_exec, or switch to Uuid::uuid1()/uuid4()/uuid6() if version-2 semantics are not required

Example fix

// before
$uuid = \Ramsey\Uuid\Uuid::uuid2(); // system UID lookup fails

// after
$uuid = \Ramsey\Uuid\Uuid::uuid2(
    \Ramsey\Uuid\Uuid::DCE_DOMAIN_PERSON,
    function_exists('posix_getuid') ? posix_getuid() : 1000,
);
Defensive patterns

Strategy: fallback

Validate before calling

if (!function_exists('shell_exec')
    || str_contains(strtolower((string) ini_get('disable_functions')), 'shell_exec')) {
    // system UID lookup will fail; supply an identifier
    $uuid = \Ramsey\Uuid\Uuid::uuid2(\Ramsey\Uuid\Uuid::DCE_DOMAIN_PERSON, posix_getuid());
}

Type guard

function canResolveSystemUid(): bool
{
    return function_exists('shell_exec')
        && !str_contains(strtolower((string) ini_get('disable_functions')), 'shell_exec');
}

Try / catch

try {
    $uuid = \Ramsey\Uuid\Uuid::uuid2($domain);
} catch (\Ramsey\Uuid\Exception\DceSecurityException $e) {
    $uuid = \Ramsey\Uuid\Uuid::uuid2($domain, 0); // explicit placeholder identifier
}

Prevention

When it happens

Trigger: Calling Uuid::uuid2() (version 2 UUID) without passing an explicit local domain identifier while shell_exec is in disable_functions, 'id' is unavailable in a minimal container, or on Windows where whoami /user output cannot be parsed. Note the empty result is cached statically, so later calls keep failing.

Common situations: Shared hosting and hardened PHP configs listing shell_exec in disable_functions; minimal Docker/Alpine images without coreutils; Windows/IIS environments with non-standard whoami output; CI sandboxes.

Related errors


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