Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Laravel: Extended exception handler improperly handles non-API operations #7466

Open
@jonerickson

Description

API Platform version(s) affected: 4.1.25

Description

When using API Platform’s Laravel integration, custom error handler callbacks defined in bootstrap/app.php (e.g. via $exceptions->respond() or $exceptions->render()) are ignored because the deferred provider replaces the default error handler with its own decorated handler before the callbacks are even registered.

In the DeferredProvider, API Platform decorates the default error handler with its own (ApiPlatform\Laravel\Exception\ErrorHandler). Inside the render() method, it checks whether the request is an API Platform operation. If not, it delegates handling to the decorated service or the parent class:

$apiOperation = $this->initializeOperation($request);
if (!$apiOperation) {
 return $this->decorated
 ? $this->decorated->render($request, $exception)
 : parent::render($request, $exception);
}

Because the deferred provider registers its bindings before the custom render/respond callbacks are registered, it extends and decorates the default error handler that contains null callbacks. When its time to check if there are any custom render/respond callbacks, because we decorated a handler that never had them set, we don't have anything to run.

Impact

  • Custom $exceptions->render() or $exceptions->respond() definitions are never called.
  • Developers cannot override exception handling when API Platform’s deferred provider is registered.

Proposed Solution

To restore expected behavior, the handler could directly call parent::render() instead of delegating to $this->decorated->render() when $apiOperation is false. This ensures Laravel’s exception handling pipeline (including user-defined callbacks) is respected. We may also try registering the APIP exception handler if the non-deferred provider. I have not tried this solution but it may be an option.

References

How to reproduce : Attempt to define your own render/respond callbacks in the bootstrap/app.php file and they fail to run.

If you dd() out the decorated handler, you'll noticed, even if you have defined your own callbacks, they have not been registered yet:

bootstrap/app.php:

->withExceptions(function (Exceptions $exceptions): void {
 $exceptions->respond(function (Response $response, Throwable $exception, Request $request) {
 ...

ApiPlatformDeferredProvider.php Line 258:

$this->app->extend(
 ExceptionHandler::class,
 function (ExceptionHandler $decorated, Application $app) {
 dd($decorated);
 /** @var ConfigRepository */
 $config = $app['config'];
 .... 

Output:

Illuminate\Foundation\Exceptions\Handler {#3084 ▼
 #container: Illuminate\Foundation\Application {[#11 ▶](https://mi.test/asd#sf-dump-1026641604-ref211)}
 #dontReport: []
 #dontReportCallbacks: []
 #reportCallbacks: []
 #levels: []
 #throttleCallbacks: []
 #contextCallbacks: []
 #renderCallbacks: []
 #shouldRenderJsonWhenCallback: null
 #finalizeResponseCallback: null
 #exceptionMap: []
 #hashThrottleKeys: true
 #internalDontReport: array:12 [▶]
 #dontFlash: array:3 [▶]
 #withoutDuplicates: false
 #reportedExceptionMap: WeakMap {#2898}
}

You'll notice finalizeResponseCallback is null, but this should be the registered respond() callback.

Additional Context

Happy to submit a PR - just need to know which direction the team would like to take.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /