phalcon/cphalcon · error · Phalcon\Tag\Exception
A dependency injection container is required to access the '
Error message
A dependency injection container is required to access the 'url' service
What it means
Phalcon\Tag's URL-related helpers (linkTo, image, stylesheets etc.) resolve the 'url' shared service from the default DI container; the resolved UrlInterface is cached statically in Tag::$urlService. When no default container exists, getUrlService() throws Phalcon\Tag\Exception ("A dependency injection container is required to access the 'url' service"). FactoryDefault registers 'url' (Phalcon\Mvc\Url) automatically — hitting this means Tag ran without a booted container.
Source
Thrown at phalcon/Tag.zep:507
public static function getTitleSeparator() -> string
{
return (string) self::documentTitleSeparator;
}
/**
* Returns a URL service from the default DI
*/
public static function getUrlService() -> <UrlInterface>
{
var url, container;
let url = self::urlService;
if typeof url != "object" {
let container = self::getDI();
if container === null {
throw new Exception(
"A dependency injection container is required to access the 'url' service"
);
}
let url = <UrlInterface> container->getShared("url"),
self::urlService = url;
}
return url;
}
/**
* Every helper calls this function to check whether a component has a
* predefined value using Phalcon\Tag::setDefault() or value from $_POST
*
* @phpstan-param tag_parameters $parameters
*/
public static function getValue(var name, array params = []) -> mixedView on GitHub (pinned to b7419de9cd)
Solutions
- Register a container: Tag::setDI($di) with $di->setShared('url', \Phalcon\Mvc\Url::class), or Di::setDefault(new FactoryDefault())
- Register 'url' explicitly if you use a bare Phalcon\Di\Di instead of FactoryDefault
- Keep tag helper usage inside the bootstrapped application lifecycle
Example fix
// before (no container)
echo \Phalcon\Tag::linkTo(['https://example.com', 'Example']); // throws
// after
$di = new \Phalcon\Di\Di();
$di->setShared('url', \Phalcon\Mvc\Url::class);
\Phalcon\Di\Di::setDefault($di);
\Phalcon\Tag::setDI($di);
echo \Phalcon\Tag::linkTo(['https://example.com', 'Example']); Defensive patterns
Strategy: validation
Validate before calling
use Phalcon\Di\Di;
use Phalcon\Mvc\Url;
use Phalcon\Tag;
if (null === Di::getDefault()) {
$di = new Di();
$di->setShared('url', Url::class);
Di::setDefault($di);
Tag::setDI($di);
}
echo \Phalcon\Tag::linkTo(['https://example.com', 'Example']); Type guard
function hasTagUrlContainer(): bool
{
return null !== \Phalcon\Di\Di::getDefault()
|| null !== \Phalcon\Tag::getDI();
} Try / catch
try {
echo \Phalcon\Tag::linkTo(['user/list', 'Users']);
} catch (\Phalcon\Tag\Exception $e) {
if (str_contains($e->getMessage(), "'url' service")) {
echo '<a href="/user/list">Users</a>'; // manual fallback
} else {
throw $e;
}
} Prevention
- Register 'url' (Phalcon\Mvc\Url) in any container used with Tag helpers
- Keep tag rendering inside the bootstrapped application; avoid Tag in container-less scripts
- Reset static state (Di::reset) between tests so cached services do not mask a missing container
When it happens
Trigger: Calling Tag::linkTo() / Tag::image() / Tag::stylesheetLink() in a unit test or CLI script; after Di::reset(); once Tag::$urlService has been cached by an earlier successful call, later calls no longer need the container (order-dependent).
Common situations: Testing view helpers in isolation; micro-apps or workers that render partials; custom bootstrap that never registers the container or calls Di::setDefault.
Related errors
- A dependency injection container is required to access the '
- Argument at position {} must have a type
- Service '{}' is required in parameter on position {}
- Service 'value' is required in parameter on position {}
- Service 'className' is required in parameter on position {}
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/b850bf300cdd0200.
Report an issue: GitHub.