guzzle/guzzle · error · \InvalidArgumentException

Cookie value must be scalar or stringable

Error message

Cookie value must be scalar or stringable

What it means

Thrown by CookieJar::fromArray() when one of the values in the input cookie array is neither a scalar (int/float/bool/string) nor an object implementing __toString(). The library needs a stringable value because it immediately casts each cookie value to a string to build a SetCookie, so a non-stringable value (array, resource, closure, plain object) cannot be represented as a cookie value.

Source

Thrown at src/Cookie/CookieJar.php:65

            $this->setCookie($cookie);
        }
    }

    /**
     * Create a new Cookie jar from an associative array and domain.
     *
     * @param array  $cookies Cookies to create the jar from
     * @param string $domain  Domain to set the cookies to
     */
    public static function fromArray(
        #[\SensitiveParameter]
        array $cookies,
        string $domain
    ): self {
        $cookieJar = new self();
        foreach ($cookies as $name => $value) {
            if (!\is_scalar($value) && !(\is_object($value) && \method_exists($value, '__toString'))) {
                throw new \InvalidArgumentException('Cookie value must be scalar or stringable');
            }

            $cookieJar->setCookie(new SetCookie([
                'Domain' => $domain,
                'Name' => (string) $name,
                'Value' => (string) $value,
                'Discard' => true,
            ]));
        }

        return $cookieJar;
    }

    /**
     * Evaluate if this cookie should be persisted to storage
     * that survives between requests.
     *
     * @param SetCookie $cookie              Being evaluated.

View on GitHub (pinned to 9b200fc580)

Solutions

  1. Coerce each value to a string before calling fromArray(), e.g. array_map('strval', $cookies) when all values are scalar.
  2. Filter out or skip non-stringable entries: only pass entries where is_scalar($v) || (is_object($v) && method_exists($v, '__toString')).
  3. If you must store structured data in a cookie, json_encode it first so the value is a string.
  4. Implement __toString() on any value object you intend to pass as a cookie value.

Example fix

// before
$jar = CookieJar::fromArray(['prefs' => ['lang' => 'en']], 'example.com');

// after
$jar = CookieJar::fromArray(
    ['prefs' => json_encode(['lang' => 'en'])],
    'example.com'
);
Defensive patterns

Strategy: validation

Validate before calling

foreach ($cookies as $name => $value) {
    if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
        throw new InvalidArgumentException("Non-stringable cookie value for '$name'");
    }
}
$jar = CookieJar::fromArray($cookies, $domain);

Type guard

function isStringableValue($value): bool
{
    return is_scalar($value)
        || (is_object($value) && method_exists($value, '__toString'));
}

Try / catch

try {
    $jar = CookieJar::fromArray($cookies, $domain);
} catch (\InvalidArgumentException $e) {
    // log and coerce values: array_map(fn($v) => is_scalar($v) ? (string)$v : '', $cookies)
}

Prevention

When it happens

Trigger: Calling CookieJar::fromArray(['foo' => ['nested' => 'array'], ...], $domain) or passing an object that does not implement __toString (e.g. a DOMNode, a stdClass without __toString) as a value. Also triggered by resources (fopen handles) or null passed as a value.

Common situations: Mapping an API response or DB row straight into fromArray() where a column is a JSON/array type instead of a scalar; passing a Carbon/DateTime object (which is stringable) works but a plain value object without __toString does not; forgetting to serialize a nested structure before storing it as a cookie.

Related errors


AI-assisted analysis of guzzle/guzzle@9b200fc580 (2026-08-04). Data as JSON: /data/errors/3242cbe8f71eb0af.json. Report an issue: GitHub.