sebastianbergmann/phpunit · error · PHPUnit\Event\RuntimeException

getrusage() returned non-integer values for "%s" and/or "%s"

Error message

getrusage() returned non-integer values for "%s" and/or "%s".

What it means

SystemCpuTimeMeter validates that the values under the rusage keys are PHP ints before handing them to CpuTime::fromSecondsAndNanoseconds(); non-integer values (strings, floats) throw this RuntimeException. Stock PHP always returns ints, so like the sibling getrusage guards this is @codeCoverageIgnore'd and points at an intercepted or patched getrusage() returning coerced values.

Source

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

        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,
                    $microsecondsKey,
                ),
            );
            // @codeCoverageIgnoreEnd
        }

        return CpuTime::fromSecondsAndNanoseconds($seconds, $microseconds * 1000);
    }
}

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Cast the stub's values to int: ['ru_utime.tv_sec' => (int) $sec, ...].
  2. Validate the environment with php -r '$u = getrusage(); var_dump(is_int($u["ru_utime.tv_sec"]));'.
  3. Catch PHPUnit\Event\RuntimeException around userCpuTime()/systemCpuTime() and degrade to time-only telemetry in constrained environments.

Example fix

// before
function getrusage(): array { return ['ru_utime.tv_sec' => '12', 'ru_utime.tv_usec' => '345']; } // strings

// after
function getrusage(): array { return ['ru_utime.tv_sec' => 12, 'ru_utime.tv_usec' => 345]; } // ints
Defensive patterns

Strategy: fallback

Validate before calling

$usage = getrusage();
if ($usage === false || !is_int($usage['ru_utime.tv_sec'] ?? null) || !is_int($usage['ru_utime.tv_usec'] ?? null)) {
    // non-integer rusage values: skip CPU-time telemetry in this environment
}

Try / catch

try {
    $cpu = $meter->userCpuTime();
} catch (PHPUnit\Event\RuntimeException $e) {
    // Values not trustworthy as ints: fall back to time-only telemetry
}

Prevention

When it happens

Trigger: A mocked getrusage() that returns string numbers ('42') or floats; serialization round-trips (e.g. a result cache) that turned ints into strings; PHP builds or extensions that alter the array's value types.

Common situations: Test doubles for getrusage() written without int casts; telemetry data crossing process boundaries through JSON; debugging tooling that rewrites native return values.

Related errors


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