Skip to content

Chained exceptions serialize as empty objects in JSON error responses #163

@jamisonbryant

Description

@jamisonbryant

Summary

When a CakePHP exception chains a previous exception via the third constructor argument, MixerApiExceptionRenderer collects the full exception chain but passes raw Throwable objects into the JSON serialization layer. Since PHP's Exception class has only protected properties (message, code, file, line, trace, previous) and does not implement JsonSerializable, json_encode produces {} for each one.

This means chained exception details are completely lost in the JSON error response.

Before (current behavior)

{
    "exception": "FailedRouteCacheException",
    "message": "Unable to cache route collection...",
    "exceptions": [{}, {}]
}

The inner exception's message -- which often contains the actual root cause -- is invisible to the developer.

After (expected behavior)

{
    "exception": "FailedRouteCacheException",
    "message": "Unable to cache route collection...",
    "exceptions": [
        {
            "class": "FailedRouteCacheException",
            "message": "Unable to cache route collection...",
            "code": 500
        },
        {
            "class": "RuntimeException",
            "message": "Serialization of 'Closure' is not allowed",
            "code": 0
        }
    ]
}

Location

plugins/exception-render/src/MixerApiExceptionRenderer.php, lines 76-81:

$exceptions = [$exception];
$previous = $exception->getPrevious();
while ($previous != null) {
    $exceptions[] = $previous;
    $previous = $previous->getPrevious();
}

This array of raw Throwable objects is passed to $this->controller->set() and serialized via JsonView.

Discovered via

The CakeDC\CachedRouting\Routing\Middleware\CachedRoutingMiddleware throws a FailedRouteCacheException that wraps the original exception. The wrapper's message says "the original exception message can show what type of object failed to serialize" -- but the renderer never surfaces that original message, making the error misleading.

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