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
- Cast the stub's values to int: ['ru_utime.tv_sec' => (int) $sec, ...].
- Validate the environment with php -r '$u = getrusage(); var_dump(is_int($u["ru_utime.tv_sec"]));'.
- 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
- Cast stubbed rusage values to int in test doubles.
- Avoid round-tripping rusage arrays through JSON/string serialization without recasting types.
- Keep CPU-time reads behind one guarded helper in custom runners so the fallback lives in a single place.
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
- getrusage() failed.
- getrusage() did not return the expected keys "%s" and "%s".
- Value for %s must not be negative.
- Value for nanoseconds must not be greater than 999999999.
- Value for %s must not be negative.
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/c8b826e00f313086.
Report an issue: GitHub.