A route declared stateless: true promises that handling it will not use the session. If the same security path also runs remember-me or session-backed browser authentication, Symfony can detect session access and throw UnexpectedSessionUsageException. Separate the security boundaries.
Last updated: November 11, 2026.
# config/packages/security.yaml
security:
firewalls:
api:
pattern: ^/api/
stateless: true
access_token: ~
main:
lazy: true
provider: app_user_provider
form_login: ~
remember_me:
secret: '%kernel.secret%'
lifetime: 604800Order the API firewall before the broader browser firewall. API clients authenticate on every request with a stateless mechanism, while browser pages may continue using form login, remember-me, and the session.
Make the route promise match the firewall
Symfony’s routing configuration reference describes the route stateless option. In debug mode, unexpected session use can raise an exception; in other environments it may be logged. The option is a diagnostic contract, not a command that magically makes session-aware authentication stateless.
The security configuration reference provides a firewall-level stateless setting. Give API routes a distinct path or host and match them with that firewall. Symfony uses the first matching firewall, so place the narrow ^/api/ rule before main and confirm the match with the security profiler. Do not enable form login or remember-me on the stateless firewall.
Choose authentication for each client
Symfony’s remember-me documentation is designed for browser authentication that persists through a cookie. It belongs with the browser firewall, where session use is allowed. A stateless API should instead validate its access token, signed request, or other credential on every request. Give the API its own entry point and access-control rules so failed authentication also returns an API response rather than a browser login redirect.
Do not hide the exception with a broad catch or start a session conditionally. That makes the route’s behavior depend on which cookies the browser happened to send. Add functional tests for an anonymous request, a valid API credential, and a request carrying the browser remember-me cookie. Each API test should complete without creating or reading a session.