phalcon/cphalcon · error · Phalcon\Container\Exceptions\ServiceNotRegistered
Service '{name}' not registered
Error message
Service '{name}' not registered What it means
getService() calls get() and then enforces that the resolved value is a PHP object; ServiceNotRegistered is thrown when the name resolves fine but to a scalar, array, or null. With this container's processors, the usual source is a closure definition whose factory returns a non-object.
Source
Thrown at phalcon/Container/Container.zep:318
}
/**
* Resolve an return a service
*
* @param string $serviceName
*
* @return object
* @throws ServiceNotFound
* @throws ServiceNotRegistered
*/
public function getService(string serviceName) -> object
{
var result;
let result = this->get(serviceName);
if (!is_object(result)) {
throw new ServiceNotRegistered(serviceName);
}
return result;
}
/**
* Returns the names of every registered service definition. Names that
* only exist as an alias, a pre-set instance or a parameter are not
* included.
*
* @return array<int, string>
*/
public function getServiceNames() -> array
{
return array_keys(this->services);
}
/**View on GitHub (pinned to b7419de9cd)
Solutions
- Store non-object values as parameters: setParameter('settings', [...]) and read with getParameter()
- Make the factory return an object (e.g. a Config/DTO object) if consumers genuinely need a service
- Use get() instead of getService() when a non-object result is legitimate for that name
- Guard manually: $result = $container->get('settings'); if (!is_object($result)) { /* parameter path */ }
Example fix
// before
$container->set('settings', fn () => ['debug' => true]);
$settings = $container->getService('settings'); // ServiceNotRegistered
// after
$container->setParameter('settings', ['debug' => true]);
$settings = $container->getParameter('settings'); Defensive patterns
Strategy: type-guard
Validate before calling
$result = $container->get('settings');
if (!is_object($result)) {
// non-object entry: treat as value/parameter, do not call getService()
throw new LogicException("'settings' does not resolve to an object.");
} Type guard
function resolvesToObject(\Phalcon\Container\Container $container, string $name): bool
{
return is_object($container->get($name));
} Try / catch
use Phalcon\Container\Exceptions\ServiceNotRegistered;
try {
$svc = $container->getService('settings');
} catch (ServiceNotRegistered $e) {
// entry is a value, not a service object; fall back to get()/getParameter()
} Prevention
- Keep a convention: services resolve to objects, values go into parameters
- Do not hand container entries to object-typed APIs without checking the resolution result
- Prefer get() + is_object() checks in generic code instead of getService()
When it happens
Trigger: $container->set('settings', fn () => ['debug' => true]); then $container->getService('settings') — the closure returns an array; likewise a closure returning a string, int, or null.
Common situations: Storing configuration arrays or primitives as container entries (set() allows any closure return) and later handing them to code that requires a service object; generic code paths that assume every container entry is an object.
Related errors
- Service '{name}' not found
- Instance '{name}' not found
- Parameter '{name}' not found
- Circular alias detected: '{alias}'
- No processor found for the given definition
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/19c3c453a2fc9328.
Report an issue: GitHub.