{"record":{"id":"12231443df94c5dc","repo":"cakephp/cakephp","slug":"flushevery-must-be-an-integer-greater-than-or-equal-to-1","errorCode":null,"errorMessage":"`flushEvery` must be an integer greater than or equal to 1","messagePattern":"`flushEvery` must be an integer greater than or equal to 1","errorType":"validation","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Http/Response/AbstractStreamResponse.php","lineNumber":151,"sourceCode":"     *\n     * @return string\n     */\n    abstract protected function contentType(): string;\n\n    /**\n     * Validate and normalize the streaming options.\n     *\n     * Subclasses overriding this method should call `parent::normalizeStreamOptions()`\n     * so the shared options (currently `flushEvery`) keep their validation.\n     *\n     * @param array<string, mixed> $options Merged options.\n     * @param array<string, mixed> $originalOptions Original options passed by the caller.\n     * @return array<string, mixed>\n     */\n    protected function normalizeStreamOptions(array $options, array $originalOptions = []): array\n    {\n        if (!is_int($options['flushEvery']) || $options['flushEvery'] < 1) {\n            throw new InvalidArgumentException('`flushEvery` must be an integer greater than or equal to 1');\n        }\n\n        return $options;\n    }\n\n    /**\n     * Apply headers derived from the active stream options.\n     *\n     * Sets the Content-Type (with charset) returned by {@see self::contentType()}\n     * and `X-Accel-Buffering: no` so reverse proxies do not buffer the body.\n     *\n     * @return void\n     */\n    protected function applyStreamingHeaders(): void\n    {\n        $charset = Configure::read('App.encoding') ?? 'UTF-8';\n        $contentType = $this->contentType() . '; charset=' . $charset;\n","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/cakephp/cakephp/blob/1128eba9b09f1946df684811350e26f2cef68fac/src/Http/Response/AbstractStreamResponse.php#L133-L169","documentation":"normalizeStreamOptions() validates the 'flushEvery' streaming option used by stream responses. It must be an integer >= 1 because it controls how many items are encoded between output flushes; zero, negative, or non-integer values are rejected with an InvalidArgumentException.","triggerScenarios":"Constructing an AbstractStreamResponse subclass (e.g. JsonStreamResponse) or calling withStreamOptions() with ['flushEvery' => 0], a negative number, a numeric string like '10', a float, or null.","commonSituations":"Passing the value from config/env as a string without casting; computing flushEvery with integer division or ceil() producing a float; defaulting the option to 0 meaning 'no flushing'.","solutions":["Pass flushEvery as an integer >= 1, e.g. (int)'10' or max(1, $n)","Cast config values: (int)Configure::read('Streaming.flushEvery')","Remove the flushEvery option to use the default instead of passing 0/null","Use max(1, (int)$value) when deriving the value dynamically"],"exampleFix":"// before\n$response->withStreamOptions(['flushEvery' => '10']);\n// after\n$response->withStreamOptions(['flushEvery' => max(1, (int)$configValue)]);","handlingStrategy":"validation","validationCode":"$flushEvery = (int)($options['flushEvery'] ?? 100);\nif ($flushEvery < 1) {\n    $flushEvery = 1;\n}\n$response->withStreamOptions(['flushEvery' => $flushEvery]);","typeGuard":"function isValidFlushEvery(mixed $v): bool {\n    return is_int($v) && $v >= 1;\n}","tryCatchPattern":"try {\n    $response = $response->withStreamOptions($options);\n} catch (InvalidArgumentException $e) {\n    $response = $response->withStreamOptions(['flushEvery' => 100]);\n}","preventionTips":["Cast config/env values to int before passing them as options","Never use 0 as a sentinel for 'no flushing'; omit the option instead","Watch for float results from ceil()/division when computing flush intervals"],"tags":["php","streaming","validation","invalid-argument"],"backgroundTag":"value-out-of-range","analyzedSha":"1128eba9b09f1946df684811350e26f2cef68fac","analyzedAt":"2026-09-12T12:07:00.388Z","contentChangedAt":"2026-09-12T12:07:00.388Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}