{"record":{"id":"89c2e68245c739cb","repo":"phalcon/cphalcon","slug":"the-parameter-must-be-an-instance-of-collection-or-89c2e6","errorCode":null,"errorMessage":"The parameter must be an instance of Collection or DiInterface","messagePattern":"The parameter must be an instance of Collection or DiInterface","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"phalcon/Support/AbstractLocator.zep","lineNumber":48,"sourceCode":"    /**\n     * @var Collection|DiInterface\n     */\n    protected container;\n\n    /**\n     * @phpstan-var array<string, class-string<T>>\n     */\n    protected array services = [];\n\n    /**\n     * @phpstan-param array<string, class-string<T>> $services\n     */\n    public function __construct(\n        var container,\n        array services = []\n    ) {\n        if (!(container instanceof Collection) && !(container instanceof DiInterface)) {\n            throw new \\TypeError(\"The parameter must be an instance of Collection or DiInterface\");\n        }\n\n        var definition, name;\n\n        let this->container = container;\n        let this->services  = this->getServices();\n\n        for name, definition in services {\n            this->register(name, definition);\n        }\n    }\n\n    /**\n     * Returns the full registered service map (defaults plus any added via\n     * register()).\n     *\n     * @return array<string, class-string<T>>\n     */","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Support/AbstractLocator.zep#L30-L66","documentation":"Phalcon\\Support\\AbstractLocator (base for service locators such as access locators) stores a container to resolve services from; its constructor accepts only Phalcon\\Contracts\\Container\\Service\\Collection (new Container) or Phalcon\\Di\\DiInterface (legacy Di) and throws \\TypeError for anything else (phalcon/Support/AbstractLocator.zep:48). The parameter is untyped on purpose to allow both, which is why the check is manual.","triggerScenarios":"new SomeLocator(null), new SomeLocator(new stdClass()), or passing a foreign container (e.g. a PSR-11 implementation) that implements neither interface.","commonSituations":"Migrating between the legacy Di and the new Container and passing the wrong object; constructing the locator before the DI exists so null slips in; assuming any container-interop object works.","solutions":["Pass a valid container: Phalcon\\Di\\Di::getDefault() (or your app's DiInterface) or a Phalcon\\Contracts\\Container\\Service\\Collection instance.","Construct the locator lazily (as a DI service/factory) so the container is guaranteed to exist at build time.","Add an instanceof check before instantiation when the container arrives from variable sources."],"exampleFix":"// before\n$locator = new AccessLocator(null); // TypeError\n\n// after\n$locator = new AccessLocator(Phalcon\\Di\\Di::getDefault());","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"use Phalcon\\Contracts\\Container\\Service\\Collection;\nuse Phalcon\\Di\\DiInterface;\n\n/** @param mixed $container @return Collection|DiInterface */\nfunction normalizeLocatorContainer(mixed $container): Collection|DiInterface\n{\n    if ($container instanceof Collection || $container instanceof DiInterface) {\n        return $container;\n    }\n    return Phalcon\\Di\\Di::getDefault();\n}","tryCatchPattern":null,"preventionTips":["Register locators as DI services so the container argument is resolved by the framework, never hand-built with null.","Construct locators after the DI is initialized (lazy factories), not during bootstrap constants.","PSR-11 or custom containers are not accepted — adapt them into a Collection first."],"tags":["phalcon","di","service-locator","typeerror","container"],"backgroundTag":"invalid-argument-type","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}