{"record":{"id":"24eb04bb2e336350","repo":"phalcon/cphalcon","slug":"a-null-key-is-not-allowed-bag-elements-must-be-wr","errorCode":null,"errorMessage":"A null key is not allowed; bag elements must be written with a string key.","messagePattern":"A null key is not allowed; bag elements must be written with a string key\\.","errorType":"exception","errorClass":"Phalcon\\Http\\Request\\Exceptions\\NullKeyException","httpStatus":null,"severity":"error","filePath":"phalcon/Http/Request/Bag/AbstractBag.zep","lineNumber":244,"sourceCode":"        return this->has((string) offset);\n    }\n\n    /**\n     * Offset to retrieve\n     */\n    public function offsetGet(mixed offset) -> mixed\n    {\n        return this->get((string) offset);\n    }\n\n    /**\n     * Offset to set\n     * @throws NullKeyException When the offset is null (append form)\n     */\n    public function offsetSet(mixed offset, mixed value) -> void\n    {\n        if null === offset {\n            throw new NullKeyException();\n        }\n\n        this->set((string) offset, value);\n    }\n\n    /**\n     * Offset to unset\n     */\n    public function offsetUnset(mixed offset) -> void\n    {\n        this->remove((string) offset);\n    }\n\n    /**\n     * Removes an element from the bag\n     *\n     * @param int|string $key\n     */","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Http/Request/Bag/AbstractBag.zep#L226-L262","documentation":"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.","triggerScenarios":"$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).","commonSituations":"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.","solutions":["Always write with an explicit string key: $bag['name'] = $value;","Guard dynamic keys before writing: if (!is_string($key) || $key === '') { $key = 'default'; }","Use the object API instead of ArrayAccess: $bag->set('name', $value);"],"exampleFix":"// before\n$bag[$row['identifier']] = $row['value']; // throws when identifier is null\n\n// after\n$key = $row['identifier'] ?? 'unnamed';\n$bag[(string) $key] = $row['value'];","handlingStrategy":"type-guard","validationCode":"$key = $row['key'] ?? null;\nif (!is_string($key) || '' === $key) {\n    throw new \\InvalidArgumentException('Bag key must be a non-empty string');\n}\n$bag[$key] = $row['value'];","typeGuard":"function isBagKey(mixed $offset): bool\n{\n    return is_string($offset) && '' !== $offset;\n}","tryCatchPattern":"try { $bag[$key] = $value; } catch (\\Phalcon\\Http\\Request\\Exceptions\\NullKeyException $e) { // map to a 400 with context\n    http_response_code(400);\n    exit('Missing key for bag element');\n}","preventionTips":["Never use the $bag[] append syntax on Bag objects","Validate dynamic keys before writing them","Static-analyze ArrayAccess usage on Bag classes to catch append forms"],"tags":["php","phalcon","request","arrayaccess","type-safety"],"backgroundTag":"null-array-key","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}