phalcon/cphalcon · error · TypeError

The parameter must be 'array' or 'string'

Error message

The parameter must be 'array' or 'string'

What it means

Phalcon\Auth\Guard\UserRemember is a value object wrapping a remember-me cookie payload. Its constructor accepts only a string (raw JSON from the cookie) or an array (already-decoded payload); anything else throws \TypeError before parsing (phalcon/Auth/Guard/UserRemember.zep:43). Note the guard is type-only: malformed JSON strings deliberately degrade to an empty payload (InvalidArgumentException is caught), so this error means the caller passed the wrong type, not bad JSON.

Source

Thrown at phalcon/Auth/Guard/UserRemember.zep:43

{
    /**
     * @var int|string|null
     */
    protected id;
    protected string token;
    protected string userAgent;

    /**
     * Accepts either the raw JSON cookie value (string) or the already
     * decoded associative array. Malformed input degrades to an empty
     * payload so callers can read getters without null-guarding.
     *
     * @param array<string, mixed>|string $payload
     */
    public function __construct(var payload)
    {
        if (typeof payload !== "array" && typeof payload !== "string") {
            throw new \TypeError("The parameter must be 'array' or 'string'");
        }

        var data, rawId;

        try {
            let data = typeof payload === "string" ? (new Decode())->__invoke(payload, true) : payload;
        } catch InvalidArgumentException {
            let data = [];
        }

        if (typeof data !== "array") {
            let data = [];
        }

        /** @var RememberPayload $data */
        let rawId = isset(data["id"]) ? data["id"] : null;

        let this->id        = (typeof rawId === "int" || typeof rawId === "string") ? rawId : null;

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Default the input: new UserRemember($_COOKIE['remember'] ?? '') — an empty string yields an empty, safely-readable payload.
  2. If decoding yourself, use json_decode($raw, true) so you pass an array, not stdClass.
  3. Guard the boundary with is_string()/is_array() when the value comes from untrusted or legacy storage.

Example fix

// before
$remember = new UserRemember($_COOKIE['remember-me'] ?? null); // TypeError

// after
$remember = new UserRemember($_COOKIE['remember-me'] ?? '');
Defensive patterns

Strategy: type-guard

Validate before calling

$raw = $_COOKIE['remember-me'] ?? '';
if (!is_string($raw)) {
    $raw = ''; // cookie storage is always string; belt-and-braces for tests
}

Type guard

/** @param mixed $value @return array|string */
function normalizeRememberPayload(mixed $value): array|string
{
    return (is_string($value) || is_array($value)) ? $value : '';
}

$remember = new UserRemember(normalizeRememberPayload($payload));

Prevention

When it happens

Trigger: new UserRemember(null) — e.g. ($_COOKIE['remember'] ?? null) when the cookie is absent; passing an int/bool/stdClass; json_decode($raw) without the true flag producing stdClass.

Common situations: Reading a possibly-missing cookie without a default; a refactor changes the producer to write arrays while an older path still passes null; test code passing 0 or false as a sentinel; decoded values forwarded without re-flagging as arrays.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/3c79f96e7ca87c22. Report an issue: GitHub.