cms
cms copied to clipboard
API call (collection/foo/entries) results in "Maximum stack depth exceeded"
Bug description
Under certain conditions, a collection with parent/child relationships can trigger a 500 Maximum stack depth exceeded if queried via API.
How to reproduce
- Create a collection
- Set "expect a root page" in the collection config
- Set the ordering to be date based (desc)
- Create 2 blueprints. One for the root page (eg "recursion_test_root") and one for the other pages (eg "recursion_test_post")
- In the root blueprint, add an "Entries" relationship field
- Configure the Entries field to accept max 1 entry from the "recursion_test_post" collection
- Create the root page
- Create a post "Post A" (this post uses the "recursion_test_post" blueprint
- Edit the Root page. Select "Post A" in the Entries field

Make an api call to /collections/recursion_test/entries?fields=title,parent&limit=4
500 error should result
Logs
[2022-07-14 01:01:00] local.ERROR: Maximum stack depth exceeded {"exception":"[object] (InvalidArgumentException(code: 0): Maximum stack depth exceeded at D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\JsonResponse.php:84)
[stacktrace]
#0 D:\\xampp\\htdocs\\recursion_test\\vendor\\symfony\\http-foundation\\JsonResponse.php(54): Illuminate\\Http\\JsonResponse->setData(Array)
#1 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\JsonResponse.php(32): Symfony\\Component\\HttpFoundation\\JsonResponse->__construct(Array, 200, Array, false)
#2 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ResponseFactory.php(99): Illuminate\\Http\\JsonResponse->__construct(Array, 200, Array, 0)
#3 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse.php(26): Illuminate\\Routing\\ResponseFactory->json(Array, 200)
#4 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Resources\\Json\\ResourceCollection.php(134): Illuminate\\Http\\Resources\\Json\\PaginatedResourceResponse->toResponse(Object(Illuminate\\Http\\Request))
#5 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Resources\\Json\\ResourceCollection.php(114): Illuminate\\Http\\Resources\\Json\\ResourceCollection->preparePaginatedResponse(Object(Illuminate\\Http\\Request))
#6 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(776): Illuminate\\Http\\Resources\\Json\\ResourceCollection->toResponse(Object(Illuminate\\Http\\Request))
#7 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(763): Illuminate\\Routing\\Router::toResponse(Object(Illuminate\\Http\\Request), Object(Illuminate\\Http\\Resources\\Json\\AnonymousResourceCollection))
#8 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(695): Illuminate\\Routing\\Router->prepareResponse(Object(Illuminate\\Http\\Request), Object(Illuminate\\Http\\Resources\\Json\\AnonymousResourceCollection))
#9 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(128): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
#10 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\Http\\Middleware\\HandleToken.php(13): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#11 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\Http\\Middleware\\HandleToken->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#12 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\SubstituteBindings.php(50): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#13 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#14 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\ThrottleRequests.php(127): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#15 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\ThrottleRequests.php(103): Illuminate\\Routing\\Middleware\\ThrottleRequests->handleRequest(Object(Illuminate\\Http\\Request), Object(Closure), Array)
#16 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\ThrottleRequests.php(55): Illuminate\\Routing\\Middleware\\ThrottleRequests->handleRequestUsingNamedLimiter(Object(Illuminate\\Http\\Request), Object(Closure), 'api', Object(Closure))
#17 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Illuminate\\Routing\\Middleware\\ThrottleRequests->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'api')
#18 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\API\\Middleware\\Cache.php(26): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#19 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\API\\Middleware\\Cache->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#20 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\Http\\Middleware\\RequireStatamicPro.php(17): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#21 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\Http\\Middleware\\RequireStatamicPro->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#22 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\Http\\Middleware\\SwapExceptionHandler.php(19): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#23 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\Http\\Middleware\\SwapExceptionHandler->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#24 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#25 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(697): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#26 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(672): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request))
#27 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(636): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route))
#28 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(625): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request))
#29 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(166): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request))
#30 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(128): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request))
#31 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\Http\\Middleware\\DisableFloc.php(18): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#32 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\Http\\Middleware\\DisableFloc->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#33 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\Http\\Middleware\\CheckMultisite.php(14): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#34 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\Http\\Middleware\\CheckMultisite->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#35 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\Http\\Middleware\\CheckComposerJsonScripts.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#36 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\Http\\Middleware\\CheckComposerJsonScripts->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#37 D:\\xampp\\htdocs\\recursion_test\\vendor\\statamic\\cms\\src\\Http\\Middleware\\PoweredByHeader.php(19): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#38 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Statamic\\Http\\Middleware\\PoweredByHeader->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#39 D:\\xampp\\htdocs\\recursion_test\\vendor\\barryvdh\\laravel-debugbar\\src\\Middleware\\InjectDebugbar.php(60): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#40 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#41 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#42 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#43 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#44 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#45 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#46 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#47 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#48 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#49 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#50 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#51 D:\\xampp\\htdocs\\recursion_test\\vendor\\fruitcake\\laravel-cors\\src\\HandleCors.php(38): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#52 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Fruitcake\\Cors\\HandleCors->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#53 D:\\xampp\\htdocs\\recursion_test\\vendor\\fideloper\\proxy\\src\\TrustProxies.php(57): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#54 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(167): Fideloper\\Proxy\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#55 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#56 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(141): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#57 D:\\xampp\\htdocs\\recursion_test\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(110): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))
#58 D:\\xampp\\htdocs\\recursion_test\\public\\index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))
#59 {main}
"}
Versions
$ php please support:details
Statamic 3.3.18 Pro Laravel 8.60.0 PHP 8.0.19 jacksleight/bard-paragraph-style 1.2.3
Installation
Fresh statamic/statamic site via CLI
Antlers Parser
regex (default)
Additional details
No response
If you're needing to get the parent entries, I'd suggest using the tree endpoint and avoid querying for the parent field.
/api/collections/recursion_test/tree?fields=title
If you're needing to get the parent entries, I'd suggest using the tree endpoint and avoid querying for the parent field.
/api/collections/recursion_test/tree?fields=title
Actually I want all the posts that match certain filters, then looping over those posts I want to grab data about each post's parent. In this way in the client application, from a single API call I can formulate a list of posts and render a hint as to their "grouping" (eg the title of parent post in the collection)
It did work. EG here is a snippet from the client application, rendered after calling the 3.2.4 API)

So in the blog tree, we have
- Blog Home (root)
- Essentials
-
- 12 valuable vocational behaviours
- Conversations
-
- The great resignation
-
- etc
The bug also affects calls to a single entry identified by its ID
GET /api/collections/{collection}/entries/{id}
Have same issue after upgrading from 3.2 to 3.3. Also, if remove parent inside vendor/laravel/framework/src/Illuminate/Http/JsonResponse.php like this for testing - no error
as i understand the problem:
- entry Page Services has parent page Home
- Home has relation field with page Contact
- Contact has parent Home as default parent
@jasonvarga I create demo repo with fresh statamic install. https://github.com/lotarbo/statamic-api-issue
superuser
[email protected]
demodemo
Only three pages: Home, First, Second; I add relation field, then in home page I add second page as relation. Then try to get data via rest api for first page and I got the same error
Still an error
Laravel: 9.35.1
PHP: 8.1.11
Statamic: 3.3.45
The issue appears to be that the "parent" entry should be "shallow" augmented, but isn't, which results in the infinite loop.
I have a workaround for you, which you can apply temporarily. I'll need some more time to investigate a proper fix.
For now, you can override the parent method in the augmented entry class. To do that you'll need to override a couple of classes.
// AppServiceProvider.php
public function register()
{
$this->app->bind(
\Statamic\Contracts\Entries\Entry::class,
\App\CustomEntry::class
);
}
// app/CustomEntry.php
<?php
namespace App;
use Statamic\Contracts\Data\Augmented;
use Statamic\Entries\Entry;
class CustomEntry extends Entry
{
public function newAugmentedInstance(): Augmented
{
return new CustomAugmentedEntry($this);
}
}
// app/CustomAugmentedEntry.php
<?php
namespace App;
use Statamic\Entries\AugmentedEntry;
class CustomAugmentedEntry extends AugmentedEntry
{
public function parent()
{
return optional($this->data->parent())->toShallowAugmentedCollection();
}
}
Another solution would be to use GraphQL, which is in my opinion far superior. The recursion would not be an issue, and you'd be able to get whatever fields you need.
query MyQuery {
entries(collection: "pages") {
data {
title
url
parent {
title
}
}
}
}
@jasonvarga thank you, but project already done, and there are no addition time to change api to GraphQL(