{"record":{"id":"b36c74e979f9cbac","repo":"phalcon/cphalcon","slug":"extender-at-key-key-for-service-service-is","errorCode":null,"errorMessage":"Extender at key '{key}' for service '{service}' is not callable","messagePattern":"Extender at key '(.+?)' for service '(.+?)' is not callable","errorType":"exception","errorClass":"Phalcon\\Container\\Exceptions\\InvalidExtender","httpStatus":null,"severity":"error","filePath":"phalcon/Container/Definition/ServiceDefinition.zep","lineNumber":435,"sourceCode":"\n    /**\n     * Set extenders\n     *\n     * @param array<array-key, callable> $extenders\n     *\n     * @return static\n     * @throws FrozenDefinition\n     * @throws InvalidExtender\n     */\n    public function setExtenders(array extenders) -> <static>\n    {\n        var extender, key;\n\n        this->checkFrozen();\n\n        for key, extender in extenders {\n            if (!is_callable(extender)) {\n                throw new InvalidExtender(this->serviceName, (string) key);\n            }\n        }\n\n        let this->extenders = extenders;\n\n        return this;\n    }\n\n    /**\n     * Set a factory\n     *\n     * @param callable $factory\n     *\n     * @return static\n     * @throws FrozenDefinition\n     */\n    public function setFactory(callable factory) -> <static>\n    {","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Container/Definition/ServiceDefinition.zep#L417-L453","documentation":"setExtenders() stores an array of decorators applied after a service is built. It validates every element with is_callable() and throws InvalidExtender on the first non-callable, including the offending array key in the message. Extend callables receive ($instance, $container).","triggerScenarios":"Passing plain strings that are not function names ('decorate'); method-name strings without an object; arrays with wrong shape; passing an instance instead of a callable; extender lists loaded from config where values are method names rather than callables.","commonSituations":"Config-driven decoration lists where each entry is a method name string; serialized extender arrays; typos in function names; copying extend() closures into setExtenders() arrays incorrectly.","solutions":["Use real callables: closures, [new Decorator, 'method'], ['Class', 'staticMethod'], or invokable objects","Validate first: $invalid = array_filter($extenders, fn ($e) => !is_callable($e)); and fail with your own message","For config-driven extenders, map names to callables before calling setExtenders()","Use the '{key}' from the message to locate exactly which array entry failed"],"exampleFix":"// before\n$def->setExtenders(['decorate']); // InvalidExtender at key 0\n\n// after\n$def->setExtenders([[new Decorator(), 'decorate']]);","handlingStrategy":"validation","validationCode":"$extenders = array_map(\n    fn (string $method) => [new Decorator(), $method],\n    $config->extenders\n);\n\n$invalid = array_keys(array_filter($extenders, fn ($e) => !is_callable($e)));\nif ($invalid !== []) {\n    throw new LogicException('Non-callable extenders at keys: ' . implode(', ', $invalid));\n}\n\n$def->setExtenders($extenders);","typeGuard":"function allCallable(array $extenders): bool\n{\n    return array_reduce($extenders, fn ($ok, $e) => $ok && is_callable($e), true);\n}","tryCatchPattern":"use Phalcon\\Container\\Exceptions\\InvalidExtender;\n\ntry {\n    $def->setExtenders($extenders);\n} catch (InvalidExtender $e) {\n    // message contains the failing key; fix that entry and re-set\n}","preventionTips":["Build extender arrays only from verified callables (closures, [object, method], invokable objects)","Never load raw method-name strings from config as extenders — map them to callables first","Remember extender signature is ($instance, $container)"],"tags":["di-container","extenders","invalid-callable","phalcon"],"backgroundTag":"invalid-callable","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}