ramsey/uuid · error · NodeException

Unable to fetch a node for this system

Error message

Unable to fetch a node for this system

What it means

SystemNodeProvider tries to find the host MAC address two ways: reading /sys/class/net/*/address (Linux sysfs) and parsing ipconfig/ifconfig/netstat output via passthru. All-zero addresses and non-matching lines are filtered out; when every avenue returns an empty string, getNode() throws NodeException('Unable to fetch a node for this system'). The empty result is memoized in a static, so retries in the same process keep failing.

Source

Thrown at src/Provider/Node/SystemNodeProvider.php:61

 */
class SystemNodeProvider implements NodeProviderInterface
{
    /**
     * Pattern to match nodes in `ifconfig` and `ipconfig` output.
     */
    private const IFCONFIG_PATTERN = '/[^:]([0-9a-f]{2}([:-])[0-9a-f]{2}(\2[0-9a-f]{2}){4})[^:]/i';

    /**
     * Pattern to match nodes in sysfs stream output.
     */
    private const SYSFS_PATTERN = '/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i';

    public function getNode(): Hexadecimal
    {
        $node = $this->getNodeFromSystem();

        if ($node === '') {
            throw new NodeException('Unable to fetch a node for this system');
        }

        return new Hexadecimal($node);
    }

    /**
     * Returns the system node if found
     */
    protected function getNodeFromSystem(): string
    {
        /** @var string | null $node */
        static $node = null;

        if ($node !== null) {
            return $node;
        }

        // First, try a Linux-specific approach.

View on GitHub (pinned to da5b521600)

Solutions

  1. Rely on the default fallback chain ([SystemNodeProvider, RandomNodeProvider]) instead of SystemNodeProvider alone
  2. Pass an explicit node to Uuid::uuid1(null, null, $node) or register a StaticNodeProvider with a chosen 12-hex value
  3. In containers, ensure /sys/class/net/*/address is readable or accept random nodes (RFC 9562 permits them)

Example fix

// before
$node = (new \Ramsey\Uuid\Provider\Node\SystemNodeProvider())->getNode();

// after
use Ramsey\Uuid\Provider\Node\FallbackNodeProvider;
use Ramsey\Uuid\Provider\Node\SystemNodeProvider;
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
$fallback = new FallbackNodeProvider([new SystemNodeProvider(), new RandomNodeProvider()]);
$node = $fallback->getNode(); // never throws unless both fail
Defensive patterns

Strategy: fallback

Validate before calling

$sysfs = glob('/sys/class/net/*/address');
$hasMac = false;
foreach ((array) $sysfs as $p) {
    $mac = trim((string) @file_get_contents($p));
    if (preg_match('/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/i', $mac) && $mac !== '00:00:00:00:00:00') {
        $hasMac = true;
        break;
    }
}
$node = $hasMac ? null : new \Ramsey\Uuid\Type\Hexadecimal('0200deadbeef'); // static fallback

Try / catch

try {
    $node = (new \Ramsey\Uuid\Provider\Node\SystemNodeProvider())->getNode();
} catch (\Ramsey\Uuid\Exception\NodeException $e) {
    // no readable MAC on this host; fall back to random node
    $node = (new \Ramsey\Uuid\Provider\Node\RandomNodeProvider())->getNode();
}

Prevention

When it happens

Trigger: Calling (new SystemNodeProvider())->getNode() or Uuid::uuid1() with a custom feature set that uses SystemNodeProvider alone, on a host where /sys/class/net is absent/unreadable, only loopback exists (00:00:00:00:00:00 is filtered), or passthru is disabled by disable_functions so the command fallback never runs. The default factory setup avoids this by falling back to RandomNodeProvider.

Common situations: Minimal Docker/distroless containers without sysfs or netstat/ifconfig; macOS/Windows where the command output format differs or tools are missing; hardened PHP with passthru in disable_functions; VMs with MAC-less virtual interfaces.

Related errors


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