symfony/http-kernel · error · InvalidArgumentException
You must either pass a RequestContext or the matcher must…
Error message
You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.
What it means
RouterListener needs a RequestContext to populate the matcher before routing. If no RequestContext was injected, the matcher must provide one via RequestContextAwareInterface; otherwise the constructor throws an InvalidArgumentException because context retrieval is impossible.
Solutions
- Pass a RequestContext explicitly: new RouterListener($matcher, $requestStack, $context).
- Use a matcher that implements RequestContextAwareInterface (e.g. Symfony\Component\Routing\Matcher\UrlMatcher).
- Extend your custom matcher from UrlMatcher or add setContext()/getContext() support.
Example fix
// before new RouterListener($myBareMatcher); // after new RouterListener($myBareMatcher, null, new RequestContext());
Defensive patterns
Strategy: validation
Validate before calling
if (!$matcher instanceof \Symfony\Component\Routing\Matcher\RequestContextAwareInterface && !isset($context)) { $context = new \Symfony\Component\Routing\RequestContext(); } Type guard
$matcher instanceof \Symfony\Component\Routing\Matcher\RequestContextAwareInterface
Try / catch
try { $routerListener = new RouterListener($matcher); } catch (\InvalidArgumentException $e) { $routerListener = new RouterListener($matcher, null, new RequestContext()); } Prevention
- Always pass a RequestContext explicitly when wiring RouterListener manually
- Prefer framework-provided matchers that implement RequestContextAwareInterface
- Type-hint construction args in DI config to catch mismatches at compile/container build time
When it happens
Trigger: Calling new RouterListener($matcher) where $matcher neither accepts a context nor implements RequestContextAwareInterface and no $context argument is supplied.
Common situations: Wiring a custom UrlMatcher/Router that only implements UrlMatcherInterface; manually constructing RouterListener in tests with a stub matcher; DIC configuration passing a bare matcher without the context argument.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Controller " " does neither exist as service nor as class.
- Controller " " cannot be fetched from the container because…
- The controller for URI
- Message built by getControllerError(): e.g. Function
- Rendering a fragment can only be done when handling a…
AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13).
Data as JSON: /api/errors/a9b1904224137d2f.
Report an issue: GitHub.
Appendix: source
Thrown at EventListener/RouterListener.php:62
class RouterListener implements EventSubscriberInterface
{
private RequestContext $context;
/**
* @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
*
* @throws \InvalidArgumentException
*/
public function __construct(
private UrlMatcherInterface|RequestMatcherInterface $matcher,
private RequestStack $requestStack,
?RequestContext $context = null,
private ?LoggerInterface $logger = null,
private ?string $projectDir = null,
private bool $debug = true,
) {
if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
}
$this->context = $context ?? $matcher->getContext();
}
private function setCurrentRequest(?Request $request): void
{
if (null !== $request) {
try {
$this->context->fromRequest($request);
} catch (\UnexpectedValueException $e) {
throw new BadRequestHttpException($e->getMessage(), $e, $e->getCode());
}
}
}
/**
* After a sub-request is done, we need to reset the routing context to the parent request so that the URL generatorView on GitHub (pinned to aa3a39d728)