phalcon/cphalcon · error · Phalcon\Mvc\Model\Exceptions\InvalidConnectionService
Invalid injected connection service
Error message
Invalid injected connection service
What it means
Thrown by Manager::getConnection() after the DI container resolved the model's connection service to something that is not an object. The service name comes from the model's getConnectionService() (default 'db') or from the manager's per-model connectionServices overrides; container->getShared(service) must return an object (a Phalcon\Db\Adapter\AdapterInterface). When the registered service returns null, a string, an array or any scalar, the connection lookup is aborted with this exception.
Source
Thrown at phalcon/Mvc/Model/Manager.zep:2491
array connectionServices
) -> <AdapterInterface> {
var container, service, connection;
let service = this->getConnectionService(model, connectionServices);
let container = <DiInterface> this->container;
if unlikely typeof container != "object" {
throw new ManagerOrmServicesUnavailable();
}
/**
* Request the connection service from the DI
*/
let connection = <AdapterInterface> container->getShared(service);
if unlikely typeof connection != "object" {
throw new InvalidConnectionService();
}
return connection;
}
/**
* @param string $collection
* @param string $modelName
* @param string $modelRelation
*
* @return bool
*/
private function checkHasRelationship(
string collection,
string modelName,
string modelRelation
) -> bool {
var entityName;View on GitHub (pinned to b7419de9cd)
Solutions
- Inspect $di->getService($model->getConnectionService()) and change its definition so every path returns a Phalcon\Db\Adapter\AdapterInterface instance.
- Verify the name: call $model->getConnectionService() (or getReadConnectionService()/getWriteConnectionService()) and confirm a service with exactly that name is registered.
- If a factory closure returns conditionally, make sure no branch returns null or an array.
- For multi-database apps, register every connection name any model references.
Example fix
// before
$di->set('db', function () {
return $this->getConfig()->database->toArray(); // array, not an adapter
});
$manager->getConnection($invoice); // InvalidConnectionService
// after
$di->set('db', function () {
$cfg = $this->getConfig()->database;
return new Phalcon\Db\Adapter\Pdo\Mysql([
'host' => $cfg->host,
'username' => $cfg->username,
'password' => $cfg->password,
'dbname' => $cfg->dbname,
]);
}); Defensive patterns
Strategy: type-guard
Validate before calling
$service = $model->getConnectionService();
if (!$di->has($service) || !is_object($di->getShared($service))) {
throw new RuntimeException('Connection service "' . $service . '" does not resolve to an object');
} Type guard
use Phalcon\Db\Adapter\AdapterInterface;
use Phalcon\Di\DiInterface;
function connectionServiceIsAdapter(DiInterface $di, string $service): bool
{
return $di->getShared($service) instanceof AdapterInterface;
} Try / catch
use Phalcon\Mvc\Model\Exceptions\InvalidConnectionService;
try {
$connection = $manager->getConnection($model);
} catch (InvalidConnectionService $e) {
// fail fast with actionable context; do not retry a misconfigured service
throw new RuntimeException(
'Service "' . $model->getConnectionService() . '" must return an AdapterInterface',
0,
$e
);
} Prevention
- Make every connection factory return AdapterInterface on all code paths; never an array or null.
- Add a boot-time smoke check: is_object($di->getShared($name)) for each configured connection name.
- Cross-check model setConnectionService() names against registered DI services in a config test.
When it happens
Trigger: A DI service registered under the model's connection service name that returns a non-object: a closure returning a config array, a service defined as raw array settings, a factory whose error path returns null, or $model->setConnectionService('databse') (typo) resolving a service that exists but is not a connection object.
Common situations: Registering 'db' as an array of connection parameters instead of a factory returning an Adapter; multi-database setups where one of the named connections was never registered; typos in setConnectionService()/setReadConnectionService()/setWriteConnectionService(); test doubles for the DI that return strings from getShared().
Related errors
- A dependency injection container is required to access inter
- The dependency injector is invalid
- A dependency injection container is required to access the s
- Class '{className}' is not an ADR Action.
- Argument at position {} must have a type
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/47d8e71370282fb8.
Report an issue: GitHub.