{"id":"5d3c548ae766ebf0","repo":"guzzle/guzzle","slug":"s-entries-must-be-strings-or-stringable-objects","errorCode":null,"errorMessage":"%s entries must be strings or stringable objects.","messagePattern":"(.+?) entries must be strings or stringable objects\\.","errorType":"exception","errorClass":"GuzzleHttp\\Exception\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Handler/CurlFactory.php","lineNumber":1569,"sourceCode":"        #[\\SensitiveParameter]\n        array &$conf\n    ): void {\n        $options = [\\CURLOPT_HTTPHEADER => 'CURLOPT_HTTPHEADER'];\n        if (\\defined('CURLOPT_PROXYHEADER')) {\n            $options[(int) \\constant('CURLOPT_PROXYHEADER')] = 'CURLOPT_PROXYHEADER';\n        }\n\n        foreach ($options as $option => $label) {\n            if (!\\array_key_exists($option, $conf) || !\\is_array($conf[$option])) {\n                continue;\n            }\n\n            $normalized = [];\n            foreach ($conf[$option] as $key => $entry) {\n                if (\\is_object($entry) && \\method_exists($entry, '__toString')) {\n                    $entry = (string) $entry;\n                } elseif (!\\is_string($entry)) {\n                    throw new InvalidArgumentException(\\sprintf('%s entries must be strings or stringable objects.', $label));\n                }\n\n                if (\\strpbrk($entry, \"\\r\\n\") !== false) {\n                    throw new InvalidArgumentException(\\sprintf('%s entries must not contain a carriage return or line feed.', $label));\n                }\n\n                $normalized[$key] = $entry;\n            }\n\n            $conf[$option] = $normalized;\n        }\n    }\n\n    /**\n     * @param array<int|string, mixed> $conf\n     */\n    private static function requiresFreshConnectionForAuthenticatedProxy(RequestInterface $request, string $proxy, array $conf): bool\n    {","sourceCodeStart":1551,"sourceCodeEnd":1587,"githubUrl":"https://github.com/guzzle/guzzle/blob/9b200fc5805036b331d6031199880dadecae0275/src/Handler/CurlFactory.php#L1551-L1587","documentation":"Thrown by normalizeCurlHeaderOptions() when an entry in CURLOPT_HTTPHEADER or CURLOPT_PROXYHEADER is neither a string nor an object implementing __toString(). cURL header arrays must be strings, so any other type (int, array, null, plain object) is rejected to avoid silent type coercion bugs.","triggerScenarios":"Passing ['curl' => [CURLOPT_HTTPHEADER => ['X-Foo: bar', ['nested']]]] or ['curl' => [CURLOPT_HTTPHEADER => ['X-Foo: bar', 123]]], where an entry is an array, integer, boolean, or non-stringable object.","commonSituations":"Building header arrays dynamically and forgetting to cast values; appending an array by mistake; passing a value object without __toString.","solutions":["Cast each header entry to a string before adding it to CURLOPT_HTTPHEADER/CURLOPT_PROXYHEADER.","Implement __toString() on value objects used as header entries.","Filter the array to remove non-string entries before passing."],"exampleFix":"// before\n['curl' => [CURLOPT_HTTPHEADER => ['Accept: application/json', $config['headerValue']]]]\n// where $config['headerValue'] is null/int.\n// after\n['curl' => [CURLOPT_HTTPHEADER => ['Accept: application/json', (string) $config['headerValue']]]]","handlingStrategy":"type-guard","validationCode":"foreach ($options['curl'][CURLOPT_HTTPHEADER] ?? [] as $entry) {\n    if (!is_string($entry) && !(is_object($entry) && method_exists($entry, '__toString'))) {\n        throw new \\InvalidArgumentException('CURLOPT_HTTPHEADER entries must be strings or stringable.');\n    }\n}","typeGuard":"/** @param mixed $entry */\nfunction isStringableHeader($entry): bool {\n    return is_string($entry) || (is_object($entry) && method_exists($entry, '__toString'));\n}","tryCatchPattern":"try {\n    $client->get($url, $options);\n} catch (\\GuzzleHttp\\Exception\\InvalidArgumentException $e) {\n    // Cast or filter header entries to strings.\n}","preventionTips":["Always cast dynamic header values to string before adding them.","Implement __toString on value objects used as headers."],"tags":["curl","headers","validation","request-options"],"analyzedSha":"9b200fc5805036b331d6031199880dadecae0275","analyzedAt":"2026-08-04T21:24:26.648Z","schemaVersion":2}