symfony/http-kernel · error · InvalidArgumentException
Rate limiter " " does not exist. Did you forget to…
Error message
Rate limiter "%s" does not exist. Did you forget to configure it? Available limiters: "%s".
What it means
RateLimitAttributeListener resolves the limiter named by the #[RateLimit] attribute from a container locator. If the named limiter service does not exist, an InvalidArgumentException is thrown listing the limiters that ARE configured.
Solutions
- Define the limiter in config: framework.rate_limiter.<name> with a factory policy matching the attribute's limiter value.
- Correct the limiter name in #[RateLimit(limiter: ...)] to match an available limiter (see the exception's list).
- Run config:dump-reference / debug:rate-limiter (if available) to verify registered limiter names.
Example fix
// before
#[RateLimit(limiter: 'api')]
// after (with config: framework: rate_limiter: { basic: ... })
#[RateLimit(limiter: 'basic')] Defensive patterns
Strategy: validation
Validate before calling
$available = array_keys($limiters->getProvidedServices());
if (!in_array($limiterName, $available, true)) { throw new \InvalidArgumentException("Unknown limiter '$limiterName'"); } Try / catch
try { $listener->onKernelControllerAttribute($event, 'kernel.controller', ...); } catch (\InvalidArgumentException $e) { /* surface misconfigured limiter name with the available list from the message */ } Prevention
- Keep #[RateLimit] limiter names in sync with framework.rate_limiter config keys
- Add a config test that dumps registered limiters
- Use a shared constant/class for limiter names instead of raw strings
When it happens
Trigger: A controller annotated with #[RateLimit(limiter: 'foo')] where no limiter named 'foo' is registered (e.g. missing limiter config under framework.rate_limiter, or a typo in the limiter name), during onKernelControllerAttribute.
Common situations: Symfony config defining limiters under a different key than the attribute; forgetting symfony/rate-limiter configuration entirely; renaming a limiter without updating attributes; typo between YAML key and attribute value.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- The "$tokens" argument of
- Invalid regular expression in the "$
- The value of the "$key" option of the
- The " " renderer does not exist.
- You must use a URI when using the ESI rendering strategy or…
AI-assisted analysis of symfony/http-kernel@aa3a39d728 (2026-09-13).
Data as JSON: /api/errors/41871ca77a3775a8.
Report an issue: GitHub.
Appendix: source
Thrown at EventListener/RateLimitAttributeListener.php:57
public function __construct(
private readonly ServiceProviderInterface $limiters,
) {
}
/**
* @param ControllerAttributeEvent<RateLimit, ControllerArgumentsEvent> $event
*/
public function onKernelControllerAttribute(ControllerAttributeEvent $event, ?string $eventName = null, ?EventDispatcherInterface $dispatcher = null): void
{
$request = $event->kernelEvent->getRequest();
$attribute = $event->attribute;
if ($attribute->methods && !\in_array($request->getMethod(), $attribute->methods, true)) {
return;
}
if (!$this->limiters->has($attribute->limiter)) {
throw new \InvalidArgumentException(\sprintf('Rate limiter "%s" does not exist. Did you forget to configure it? Available limiters: "%s".', $attribute->limiter, implode('", "', array_keys($this->limiters->getProvidedServices()))));
}
if (null === $attribute->key) {
$key = ($request->getClientIp() ?? 'unknown').'~'.$request->getMethod().'~'.$request->getPathInfo();
} elseif (!\is_string($key = $event->evaluate($attribute->key))) {
throw new \TypeError(\sprintf('The value of the "$key" option of the "%s" attribute must evaluate to a string, "%s" given.', RateLimit::class, get_debug_type($key)));
}
$rateLimit = $this->limiters->get($attribute->limiter)->create($key)->consume($attribute->tokens);
$candidate = $attribute->exposeHeaders && null !== $rateLimit->getResetAt()
? new AppliedRateLimit($rateLimit, $attribute->tokens)
: null;
if (!$rateLimit->isAccepted()) {
$request->attributes->set(self::RATE_LIMIT_ATTRIBUTE, $candidate);
if ($dispatcher && class_exists(RateLimitExceededEvent::class)) {View on GitHub (pinned to aa3a39d728)