sebastianbergmann/phpunit · error · PHPUnit\Event\RuntimeException

getrusage() did not return the expected keys "%s" and "%s".

Error message

getrusage() did not return the expected keys "%s" and "%s".

What it means

After a successful getrusage(), SystemCpuTimeMeter expects the POSIX keys 'ru_utime.tv_sec'/'ru_utime.tv_usec' (or 'ru_stime.*') in the returned array. If either key is missing, it throws this RuntimeException. Like the other getrusage guards it is @codeCoverageIgnore'd because real PHP always returns those keys; only a non-standard or intercepted getrusage() returning a different array shape can trigger it.

Source

Thrown at src/Event/Value/Telemetry/SystemCpuTimeMeter.php:58

    /**
     * @param 'ru_stime.tv_sec'|'ru_utime.tv_sec'   $secondsKey
     * @param 'ru_stime.tv_usec'|'ru_utime.tv_usec' $microsecondsKey
     *
     * @throws RuntimeException
     */
    private function cpuTime(string $secondsKey, string $microsecondsKey): CpuTime
    {
        $usage = getrusage();

        if ($usage === false) {
            // @codeCoverageIgnoreStart
            throw new RuntimeException('getrusage() failed.');
            // @codeCoverageIgnoreEnd
        }

        if (!isset($usage[$secondsKey]) || !isset($usage[$microsecondsKey])) {
            // @codeCoverageIgnoreStart
            throw new RuntimeException(
                sprintf(
                    'getrusage() did not return the expected keys "%s" and "%s".',
                    $secondsKey,
                    $microsecondsKey,
                ),
            );
            // @codeCoverageIgnoreEnd
        }

        $seconds      = $usage[$secondsKey];
        $microseconds = $usage[$microsecondsKey];

        if (!is_int($seconds) || !is_int($microseconds)) {
            // @codeCoverageIgnoreStart
            throw new RuntimeException(
                sprintf(
                    'getrusage() returned non-integer values for "%s" and/or "%s".',
                    $secondsKey,

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Inspect what getrusage() actually returns in that environment: php -r 'var_dump(array_keys(getrusage()));' and compare against ru_utime.tv_sec/ru_utime.tv_usec/ru_stime.*.
  2. Fix or remove the function override so the stock array shape is preserved.
  3. Catch PHPUnit\Event\RuntimeException around the meter calls and skip CPU-time reporting when the environment is known to be constrained.

Example fix

// stub fix: return the POSIX shape
// before
function getrusage(): array { return ['utime_sec' => 1, 'utime_usec' => 500]; }

// after
function getrusage(): array { return ['ru_utime.tv_sec' => 1, 'ru_utime.tv_usec' => 500, 'ru_stime.tv_sec' => 0, 'ru_stime.tv_usec' => 0]; }
Defensive patterns

Strategy: fallback

Validate before calling

$usage = getrusage();
if ($usage === false || !isset($usage['ru_utime.tv_sec'], $usage['ru_utime.tv_usec'])) {
    // rusage array shape unsupported here; skip CPU-time telemetry
}

Try / catch

try {
    $cpu = $meter->userCpuTime();
} catch (PHPUnit\Event\RuntimeException $e) {
    // Unexpected getrusage() shape: degrade to time-only reporting
}

Prevention

When it happens

Trigger: A shadowed/mocked getrusage() (namespace 'use function' trick, uopz, runkit7) returning a partial or renamed array; platform abstractions or patched PHP builds that alter the rusage array structure.

Common situations: Unit tests of telemetry code with hand-rolled getrusage stubs; exotic SAPIs; debugging sessions where a debugger extension rewrites native function results.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/1dcec2ce4f91e2d8. Report an issue: GitHub.