{"record":{"id":"4df3fbaa2638e321","repo":"phalcon/cphalcon","slug":"cannot-resolve-parameter-param-for-classnam","errorCode":null,"errorMessage":"Cannot resolve parameter '${param}' for '{className}'","messagePattern":"Cannot resolve parameter '(.+?)' for '(.+?)'","errorType":"exception","errorClass":"Phalcon\\Container\\Exceptions\\CannotResolveParameter","httpStatus":null,"severity":"error","filePath":"phalcon/Container/Resolver/Resolver.zep","lineNumber":180,"sourceCode":"            let typeName = type->getName();\n\n            if (method_exists(ioc, \"has\") && ioc->has(typeName)) {\n                return ioc->get(typeName);\n            }\n        }\n\n        if (parameter->isOptional()) {\n            if (parameter->isDefaultValueAvailable()) {\n                return parameter->getDefaultValue();\n            }\n\n            return null;\n        }\n\n        let declaringClass = parameter->getDeclaringClass();\n        let declaringName  = declaringClass !== null ? declaringClass->getName() : \"unknown\";\n\n        throw new CannotResolveParameter(\n            parameter->getName(),\n            declaringName\n        );\n    }\n\n    public function resolveParameters(\n        object ioc,\n        array parameters,\n        array arguments\n    ) -> array {\n        var resolved, position, parameter, name;\n\n        let resolved = [];\n\n        for position, parameter in parameters {\n            let name = parameter->getName();\n\n            if (array_key_exists(position, arguments)) {","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Container/Resolver/Resolver.zep#L162-L198","documentation":"When autowiring a class-based definition, freeze() asks the Resolver to supply constructor parameters. A parameter that is not a class the container has (or can autowire), is not optional, and has no default value triggers CannotResolveParameter, naming the parameter and its declaring class. Scalar/untyped required constructor args are the classic cause.","triggerScenarios":"class PaymentService { public function __construct(string $apiKey) {} } resolved via get(PaymentService::class) with no constructorArgs; a required interface-typed parameter whose implementation was never set(); a required param typed to a class that is itself unresolvable.","commonSituations":"Autowiring controllers or handlers with scalar config (API keys, paths, DSN parts); forgetting to bind an interface; adding a new required constructor argument during refactoring without updating registrations.","solutions":["Provide the argument explicitly: $container->set(Svc::class, Svc::class)->setConstructorArgs([new Env('API_KEY')])","Bind any missing interface: $container->set(CacheInterface::class, RedisCache::class)","Give the parameter a default value or make it optional if it is genuinely optional","Move scalar config out of constructors into a config object that is itself resolvable from the container"],"exampleFix":"// before\nclass PaymentService {\n    public function __construct(private string $apiKey) {}\n}\n$container->setAutowire(true);\n$container->get(PaymentService::class); // CannotResolveParameter: $apiKey\n\n// after\n$container->set(PaymentService::class, PaymentService::class)\n    ->setConstructorArgs([new \\Phalcon\\Container\\Resolver\\Lazy\\Env('PAYMENT_KEY')]);\n$container->get(PaymentService::class);","handlingStrategy":"validation","validationCode":"// Verify all constructor params of a class are satisfiable before autowiring\nfunction autowirable(\\Phalcon\\Container\\Container $c, string $class): bool\n{\n    $ctor = (new \\ReflectionClass($class))->getConstructor();\n    if ($ctor === null) {\n        return true;\n    }\n    foreach ($ctor->getParameters() as $p) {\n        if ($p->isOptional()) {\n            continue;\n        }\n        $type = $p->getType();\n        if ($type instanceof \\ReflectionNamedType && !$type->isBuiltin()) {\n            if (!$c->has($type->getName())) {\n                return false;\n            }\n            continue;\n        }\n        return false; // required scalar param: cannot be autowired\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"use Phalcon\\Container\\Exceptions\\CannotResolveParameter;\n\ntry {\n    $svc = $container->get(PaymentService::class);\n} catch (CannotResolveParameter $e) {\n    // message names the param and class; register an explicit binding and retry\n    $container->set(PaymentService::class, PaymentService::class)\n        ->setConstructorArgs([getenv('PAYMENT_KEY')]);\n    $svc = $container->get(PaymentService::class);\n}","preventionTips":["Never rely on autowiring for scalar constructor args — pass them via setConstructorArgs() or Lazy\\Env","Bind every interface dependency explicitly in providers","When adding a required constructor arg, update all container registrations for that class"],"tags":["di-container","autowire","reflection","constructor-injection","phalcon"],"backgroundTag":"autowire-unresolved-dependency","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}