phalcon/cphalcon · error · Phalcon\Http\Request\Exceptions\NullKeyException

A null key is not allowed; bag elements must be written with

Error message

A null key is not allowed; bag elements must be written with a string key.

What it means

Phalcon\Http\Request\Bag\AbstractBag implements ArrayAccess but does not support the append form: offsetSet() throws NullKeyException when the offset is null, i.e. $bag[] = $value. Bag entries must be written with string keys; reads and unsets cast the offset to string, but writes reject null outright.

Source

Thrown at phalcon/Http/Request/Bag/AbstractBag.zep:244

        return this->has((string) offset);
    }

    /**
     * Offset to retrieve
     */
    public function offsetGet(mixed offset) -> mixed
    {
        return this->get((string) offset);
    }

    /**
     * Offset to set
     * @throws NullKeyException When the offset is null (append form)
     */
    public function offsetSet(mixed offset, mixed value) -> void
    {
        if null === offset {
            throw new NullKeyException();
        }

        this->set((string) offset, value);
    }

    /**
     * Offset to unset
     */
    public function offsetUnset(mixed offset) -> void
    {
        this->remove((string) offset);
    }

    /**
     * Removes an element from the bag
     *
     * @param int|string $key
     */

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Always write with an explicit string key: $bag['name'] = $value;
  2. Guard dynamic keys before writing: if (!is_string($key) || $key === '') { $key = 'default'; }
  3. Use the object API instead of ArrayAccess: $bag->set('name', $value);

Example fix

// before
$bag[$row['identifier']] = $row['value']; // throws when identifier is null

// after
$key = $row['identifier'] ?? 'unnamed';
$bag[(string) $key] = $row['value'];
Defensive patterns

Strategy: type-guard

Validate before calling

$key = $row['key'] ?? null;
if (!is_string($key) || '' === $key) {
    throw new \InvalidArgumentException('Bag key must be a non-empty string');
}
$bag[$key] = $row['value'];

Type guard

function isBagKey(mixed $offset): bool
{
    return is_string($offset) && '' !== $offset;
}

Try / catch

try { $bag[$key] = $value; } catch (\Phalcon\Http\Request\Exceptions\NullKeyException $e) { // map to a 400 with context
    http_response_code(400);
    exit('Missing key for bag element');
}

Prevention

When it happens

Trigger: $bag[] = 'value'; via ArrayAccess; or $bag[$key] = $value where the dynamic $key variable is null (e.g. a missing field in a JSON payload or DB row).

Common situations: Porting plain-PHP array append code to a Bag; dynamic keys from external data where a field is absent; generic ArrayAccess-based templating or hydration code reused across containers.

Related errors


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