Return null when \Drupal::service() is called for non-existent service

Created on 9 July 2025, 4 days ago

Problem/Motivation

If \Drupal::service() is called for a non-existent service, it will throw Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service. This means that code like this may have to be used: $service = \Drupal::hasService('service') ? \Drupal::service('service') : NULL;

Steps to reproduce

Run \Drupal::service('non-existent-service').

Proposed resolution

Make it so that \Drupal::service() returns null for a non-existent service.

Remaining tasks

Implement.

User interface changes

None.

Introduced terminology

None.

API changes

\Drupal::service() returns null instead of throwing ServiceNotFoundException.

Data model changes

None.

Release notes snippet

📌 Task
Status

Active

Version

11.0 🔥

Component

base system

Created by

🇨🇦Canada Liam Morland Ontario, CA 🇨🇦

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @Liam Morland
  • 🇬🇧United Kingdom longwave UK

    I don't think we can do this without breaking existing code that expects to catch the exception.

    Ideally you should avoid \Drupal::service() and use dependency injection instead.

    One possible option is add a second argument to \Drupal::service() that passes through the second $invalid_behavior argument to the container, so you could do

    \Drupal::service('non-existent-service', ContainerInterface::NULL_ON_INVALID_REFERENCE);
    
  • 🇨🇦Canada Liam Morland Ontario, CA 🇨🇦

    I am encountering this issue in hook_preprocess_HOOK(), so dependency injection is not possible. I'm using this to adjust the behaviour of the code based on whether or not another module is installed.

    Is catching the exception better than just using \Drupal::hasService()?

    I like the idea of adding a second param.

  • 🇬🇧United Kingdom longwave UK

    Preprocess functions can be OOP and use DI since 11.2! https://www.drupal.org/node/3496491

    I think catching the exception is fine if it makes the code easier to read.

  • 🇨🇦Canada Liam Morland Ontario, CA 🇨🇦

    Due to module support, it will be a while before we can move to Drupal 11.

    Option 1:

    $service = \Drupal::hasService('service') ? \Drupal::service('service') : NULL;

    Option 2:

    try {
      $service = \Drupal::service('service');
    }
    catch (ServiceNotFoundException) {
      $service = NULL;
    }

    Option 1 is more compact.

    I would rather just do:

    $service = \Drupal::service('service');

    Or:

    $service = \Drupal::service('service', ContainerInterface::NULL_ON_INVALID_REFERENCE);

    (The code later, in a loop, tests if $service has a value and uses the service if it does.)

Production build 0.71.5 2024