{"record":{"id":"4df5f70c35b80a9b","repo":"sebastianbergmann/phpunit","slug":"value-for-nanoseconds-must-not-be-greater-than-999-4df5f7","errorCode":null,"errorMessage":"Value for nanoseconds must not be greater than 999999999.","messagePattern":"Value for nanoseconds must not be greater than 999999999\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Event/Value/Telemetry/HRTime.php","lineNumber":106,"sourceCode":"    private function ensureNotNegative(int $value, string $type): void\n    {\n        if ($value < 0) {\n            throw new InvalidArgumentException(\n                sprintf(\n                    'Value for %s must not be negative.',\n                    $type,\n                ),\n            );\n        }\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    private function ensureNanoSecondsInRange(int $nanoseconds): void\n    {\n        if ($nanoseconds > 999999999) {\n            throw new InvalidArgumentException(\n                'Value for nanoseconds must not be greater than 999999999.',\n            );\n        }\n    }\n}\n","sourceCodeStart":88,"sourceCodeEnd":112,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Event/Value/Telemetry/HRTime.php#L88-L112","documentation":"HRTime's constructor caps nanoseconds at 999999999 (ensureNanoSecondsInRange()). Because hrtime(true) returns one total-nanoseconds integer, feeding that value (or any unsplit difference of such totals) into the nanoseconds parameter of fromSecondsAndNanoseconds() is the classic trigger.","triggerScenarios":"HRTime::fromSecondsAndNanoseconds(0, hrtime(true)); computing a difference of two hrtime(true) totals and passing it as nanoseconds; converting a microsecond value with a 1000000 factor.","commonSituations":"Custom stopwatch/telemetry code switching between hrtime(true) and the (seconds, nanoseconds) pair; adapting example code written for total-nanosecond APIs; test fixtures generated from raw timestamps.","solutions":["Split totals before constructing: $nanos = hrtime(true) - $t0; then seconds = intdiv($nanos, 1000000000), nanoseconds = $nanos % 1000000000.","Prefer hrtime(false) which already returns the [seconds, nanoseconds] pair the constructor wants.","Watch unit factors: microseconds need * 1000 to become nanoseconds, not * 1000000."],"exampleFix":"// before\n$total = hrtime(true);\n$stamp = HRTime::fromSecondsAndNanoseconds(0, $total); // way over 999999999\n\n// after\n[$seconds, $nanoseconds] = hrtime(false);\n$stamp = HRTime::fromSecondsAndNanoseconds($seconds, $nanoseconds);","handlingStrategy":"validation","validationCode":"[$seconds, $nanoseconds] = hrtime(false); // already a normalized pair\n// or, from a total:\n$total       = hrtime(true) - $t0;\n$seconds     = intdiv($total, 1000000000);\n$nanoseconds = $total % 1000000000;\n\n$stamp = HRTime::fromSecondsAndNanoseconds($seconds, $nanoseconds);","typeGuard":"function isNormalizedNanoseconds(int $nanoseconds): bool\n{\n    return $nanoseconds >= 0 && $nanoseconds <= 999999999;\n}","tryCatchPattern":null,"preventionTips":["Prefer hrtime(false) over hrtime(true) when building HRTime values.","Split any hrtime(true) total with intdiv/modulo 1000000000 before constructing.","Keep microsecond-to-nanosecond factors straight (* 1000)."],"tags":["phpunit","telemetry","value-object","hrtime","unit-conversion","php"],"backgroundTag":"nanoseconds-overflow","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}