{"record":{"id":"97f42029636bea0f","repo":"phalcon/cphalcon","slug":"cannot-modify-frozen-definition-name","errorCode":null,"errorMessage":"Cannot modify frozen definition '{name}'","messagePattern":"Cannot modify frozen definition '(.+?)'","errorType":"exception","errorClass":"Phalcon\\Container\\Exceptions\\FrozenDefinition","httpStatus":null,"severity":"error","filePath":"phalcon/Container/Definition/ServiceDefinition.zep","lineNumber":542,"sourceCode":"     */\n    public function unsetFactory() -> <static>\n    {\n        this->checkFrozen();\n        let this->factory = null;\n\n        return this;\n    }\n\n    /**\n     * Check if frozen\n     *\n     * @return void\n     * @throws FrozenDefinition\n     */\n    protected function checkFrozen() -> void\n    {\n        if (this->frozen) {\n            throw new FrozenDefinition(this->serviceName);\n        }\n    }\n\n    /**\n     * Resolve arguments\n     *\n     * @param object $container\n     * @param array  $args\n     *\n     * @return array\n     */\n    private function resolveArgs(object container, array args) -> array\n    {\n        var resolved, key, argument;\n\n        let resolved = [];\n\n        for key, argument in args {","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Container/Definition/ServiceDefinition.zep#L524-L560","documentation":"A ServiceDefinition freezes the first time the container resolves it: resolve() calls definition->freeze() before building, and checkFrozen() thereafter blocks every mutation (setClass, setFactory, setExtenders, setConstructorArgs, ...). FrozenDefinition means you tried to reconfigure a service that was already instantiated.","triggerScenarios":"$container->get('db'); followed by $container->getDefinition('db')->setClass(OtherConnection::class); tests mutating definitions between cases without a fresh container; runtime overrides in code that runs after something else already resolved the singleton.","commonSituations":"Test suites reusing one container across cases; plugins overriding services after boot resolution; long-running workers (Swoole, queues) where an early request already called get().","solutions":["Re-register instead of mutating: $container->set('db', NewConnection::class) installs a fresh, unfrozen definition","Configure definitions fully before the first get() — ideally inside provider registration","Build a new container (via ContainerFactory) when a clean state is needed, the usual fix in tests","Order bootstrap so all overrides run before the first resolution of the affected service"],"exampleFix":"// before\n$container->get('db');\n$container->getDefinition('db')->setClass(OtherConnection::class); // FrozenDefinition\n\n// after\n$container->get('db');\n$container->set('db', OtherConnection::class);","handlingStrategy":"validation","validationCode":"// Mutate only definitions that have not been resolved yet\nif (!$container->hasInstance('db')) {\n    $container->getDefinition('db')->setClass(OtherConnection::class);\n} else {\n    $container->set('db', OtherConnection::class); // replace instead of mutate\n}","typeGuard":null,"tryCatchPattern":"use Phalcon\\Container\\Exceptions\\FrozenDefinition;\n\ntry {\n    $container->getDefinition('db')->setFactory($fn);\n} catch (FrozenDefinition $e) {\n    $container->set('db', $fn); // re-register a fresh definition instead\n}","preventionTips":["Finish all definition configuration before the first get(); treat post-resolution edits as bugs","In tests, build a fresh container per case instead of reconfiguring a shared one","Prefer set() to replace a definition rather than mutating an existing one at runtime"],"tags":["di-container","immutable","frozen-definition","phalcon"],"backgroundTag":"immutable-object-modified","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}