How to debug the Symfony service container

The Symfony service container decides which objects are built and injected when controllers, console commands, event subscribers, and application services run. Inspecting the compiled container helps when a type-hint receives an unexpected service, a tagged class is missing, or a custom service is not visible from bin/console.

The debug:container command reads the container for one environment and shows service IDs, aliases, tags, constructor arguments, and usages. The debug:autowiring command is the clearer view when the question is which class or interface to type-hint, or which #[Target] variant Symfony will inject.

Run the checks from the project root that contains bin/console. Use the same environment as the failure, because dev, test, and prod can load different bundles, configuration blocks, debug wrappers, and optimized services.

Steps to debug the Symfony service container:

  1. Open a terminal in the Symfony project root.
  2. Confirm the console environment that will be inspected.
    $ php bin/console about
     -------------------- --------------------------------- 
      Symfony                                               
     -------------------- --------------------------------- 
      Version              v8.1.0                           
      Environment          dev                              
      Debug                true                             
     -------------------- --------------------------------- 
      PHP                                                   
     -------------------- --------------------------------- 
      Version              8.4.22                           
      OPcache              Enabled                          
     -------------------- --------------------------------- 

    Pass --env=prod, --env=test, or --no-debug to the later debug commands when the failing behavior appears outside the default dev container.

  3. Search for the service ID, alias, or short term from the error message.
    $ php bin/console debug:container mailer
    
     // This service is a private alias for the service mailer.mailer               
    
    Information for Service "mailer.mailer"
    =======================================
    
     ---------------- --------------------------------------------- 
      Option           Value                                        
     ---------------- --------------------------------------------- 
      Service ID       mailer.mailer                                
      Class            Symfony\Component\Mailer\Mailer              
      Public           no                                           
      Arguments        Service(mailer.transports)                   
                       Service(debug.traced.messenger.bus.default)  
                       Service(debug.event_dispatcher)              
      Usages           mailer                                       
                       Symfony\Component\Mailer\MailerInterface     
     ---------------- --------------------------------------------- 
    
     ! [NOTE] The "mailer" service or alias has been removed or inlined when the    
     !        container was compiled.

    The alias line, Class, Arguments, and Usages fields identify what Symfony will build or inject. A removed-or-inlined note is common for private optimized services and is not by itself a registration failure.

  4. Check the autowiring type-hints when a constructor receives the wrong dependency.
    $ php bin/console debug:autowiring logger
    
    Autowirable Types
    =================
    
     Use the following classes & interfaces as type-hints in constructor arguments to autowire services.
     Add #[Target('name')] to the argument to select a specific variant.
     (only showing classes/interfaces matching logger)
     
     Psr\Log\LoggerInterface -> monolog.logger
       Describes a logger instance.
       #[Target('asset_mapper')] -> monolog.logger.asset_mapper
       #[Target('cache')] -> monolog.logger.cache
       #[Target('console')] -> monolog.logger.console
       #[Target('debug')] -> monolog.logger.debug
       #[Target('deprecation')] -> monolog.logger.deprecation
       #[Target('doctrine')] -> monolog.logger.doctrine
       #[Target('event')] -> monolog.logger.event
       #[Target('http_client')] -> monolog.logger.http_client
       #[Target('mailer')] -> monolog.logger.mailer
    ##### snipped #####

    Use the plain interface when the default service is correct. Use #[Target('mailer')] or another listed target when the constructor needs a named variant.

  5. List services for the tag when autoconfiguration or event registration is the suspected layer.
    $ php bin/console debug:container --tag=kernel.event_subscriber
    
    Symfony Container Services Tagged with "kernel.event_subscriber" Tag
    ====================================================================
    
     ----------------------------------------------------------------------- -------------------------------------- --------------------------------------------------------------------------------------- 
      Service ID                                                              dispatcher                             Class name                                                                             
     ----------------------------------------------------------------------- -------------------------------------- --------------------------------------------------------------------------------------- 
      console.error_listener                                                                                         Symfony\Component\Console\EventListener\ErrorListener                                  
      argument_resolver.request_payload                                                                              Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestPayloadValueResolver   
      response_listener                                                                                              Symfony\Component\HttpKernel\EventListener\ResponseListener                            
      locale_listener                                                                                                Symfony\Component\HttpKernel\EventListener\LocaleListener                              
      validate_request_listener                                                                                      Symfony\Component\HttpKernel\EventListener\ValidateRequestListener                     
    ##### snipped #####
      web_profiler.debug_toolbar                                                                                     Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener                 
      controller.is_granted_attribute_listener                                                                       Symfony\Component\Security\Http\EventListener\IsGrantedAttributeListener               
      security.listener.check_authenticator_credentials                                                              Symfony\Component\Security\Http\EventListener\CheckCredentialsListener                 
     ----------------------------------------------------------------------- -------------------------------------- --------------------------------------------------------------------------------------- 

    Replace kernel.event_subscriber with the tag named in the error, bundle documentation, or expected autoconfiguration path, such as console.command, messenger.message_handler, or twig.extension.

  6. Inspect the application service loading rules when a class under src/ is missing.
    $ cat config/services.yaml
    # yaml-language-server: $schema=../vendor/symfony/dependency-injection/Loader/schema/services.schema.json
    
    parameters:
    
    services:
        # default configuration for services in *this* file
        _defaults:
            autowire: true      # Automatically injects dependencies in your services.
            autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
    
        # makes classes in src/ available to be used as services
        # this creates a service per class whose id is the fully-qualified class name
        App\:
            resource: '../src/'
    
        # add more service definitions when explicit configuration is needed
        # please note that last definitions always *replace* previous ones

    If the class is outside the loaded resource path, excluded by a later rule, or overridden by a later definition, adjust the service configuration before searching the container again.

  7. Re-run an exact service or type-hint lookup after choosing the ID to use in code or configuration.
    $ php bin/console debug:container Psr\\Log\\LoggerInterface
    
     // This service is a private alias for the service monolog.logger              
    
    Information for Service "monolog.logger"
    ========================================
    
     Monolog log channel
    
     ---------------- ---------------------------------------------------- 
      Option           Value                                               
     ---------------- ---------------------------------------------------- 
      Service ID       monolog.logger                                      
      Class            Monolog\Logger                                      
      Tags             monolog.channel_logger                              
      Calls            useMicrosecondTimestamps, pushHandler, pushHandler  
      Public           no                                                  
      Arguments        app                                                 
      Usages           logger                                              
                       Psr\Log\LoggerInterface                             
                       error_handler.error_renderer.html                   
                       asset_mapper.compressor                             
                       doctrine.migrations.dependency_factory              
     ---------------- ----------------------------------------------------