Uncaught ErrorException: var_export does not handle circular references
genesiscz opened this issue · 13 comments
Describe the bug
When there's a circular reference in an object, I am getting a PHP Warning: Uncaught ErrorException: var_export does not handle circular references in /.../vendor/spatie/ray/src/Payloads/LogPayload.php:64
even though I am on 1.37.3 version which has try try/catch
try {
return var_export($value, true);
} catch (Exception $ex) {
return '';
}
It is quite weird because I thought that ErrorException is a children of Exception. It is even more weird that I am getting out of memory exception in the Ray itself on the same line.
Versions
- spatie/ray package version: 1.37.3
- spatie/laravel-ray package version (if applicable): 1.32.6
- PHP version: 8.2
- Laravel version (if applicable): 10.XX
Downgrading to 1.37.2
worked for me.
@genesiscz @bartbrinkman I added an extra check for recursiveness before doing the var_export. Could you give 1.37.5 a try?
@timvandijck Still broken with 1.37.5
@genesiscz @bartbrinkman I added an extra check for recursiveness before doing the var_export. Could you give 1.37.5 a try?
Can you help me understand what the clipboard means? And isn't doing this check just resulting in Ray not receiving what it should?
In my case, this fix doesn't help, because I have magic __debugInfo() in my BaseModel which is being checked for recursiveness but results in false negative because I am redacting some of the key-values because of other dumpings (including ray). My print_r looks like this:
App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper Object
(
[lastDistributionType:App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper:private] => exclusive
[cascadeOfferItemGroups] => Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => App\Collections\CascadeOfferItemsCollection Object
(
[items:protected] => Array
(
[0] => App\Models\CascadeOfferItem Object
(
[guarded:protected] => Array
(
)
[fillable:protected] => Array
(
)
[original:protected] => retracted
[netteRow:protected] => retracted
[notDbValues] => retracted
[notApiValues:protected] => Array
(
)
)
)
[escapeWhenCastingToString:protected] =>
)
[1] => App\Collections\CascadeOfferItemsCollection Object
(
[items:protected] => Array
(
[0] => App\Models\CascadeOfferItem Object
(
[guarded:protected] => Array
(
)
[fillable:protected] => Array
(
)
[original:protected] => retracted
[netteRow:protected] => retracted
[notDbValues] => retracted
[notApiValues:protected] => Array
(
)
)
)
[escapeWhenCastingToString:protected] =>
)
[2] => App\Collections\CascadeOfferItemsCollection Object
(
[items:protected] => Array
(
[0] => App\Models\CascadeOfferItem Object
(
[guarded:protected] => Array
(
)
[fillable:protected] => Array
(
)
[original:protected] => retracted
[netteRow:protected] => retracted
[notDbValues] => retracted
[notApiValues:protected] => Array
(
)
)
[1] => App\Models\CascadeOfferItem Object
(
[guarded:protected] => Array
(
)
[fillable:protected] => Array
(
)
[original:protected] => retracted
[netteRow:protected] => retracted
[notDbValues] => retracted
[notApiValues:protected] => Array
(
)
)
)
[escapeWhenCastingToString:protected] =>
)
[3] => App\Collections\CascadeOfferItemsCollection Object
(
[items:protected] => Array
(
[0] => App\Models\CascadeOfferItem Object
(
[guarded:protected] => Array
(
)
[fillable:protected] => Array
(
)
[original:protected] => retracted
[netteRow:protected] => retracted
[notDbValues] => retracted
[notApiValues:protected] => Array
(
)
)
)
[escapeWhenCastingToString:protected] =>
)
)
[escapeWhenCastingToString:protected] =>
)
)
Unfortunatelly even after commenting these methods, it won't start working. Even worse, the print_r is now resulting in memory error:
PHP Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 803213312 bytes) in /.../vendor/spatie/ray/src/Payloads/LogPayload.php on line 84
Maybe it's a bug in PHP not being able to detect the RECURSION because I have some weird recursion there? To be honest, I can't even find a documented *RECURSION*
detection in the print_r itself: https://www.php.net/manual/en/function.print-r.php
@genesiscz @bartbrinkman I added an extra check for recursiveness before doing the var_export. Could you give 1.37.5 a try?
Can you help me understand what the clipboard means? And isn't doing this check just resulting in Ray not receiving what it should?
It was added to support the new copy button that allows you to copy the output in the Ray app. We need to send it in a different way (var_export) to make it usefull.
The copy button will not be shown if we detect a circular reference because it's hard to output that in a string format and var_export doesn't even support it. Most of the time these aren't the variables you would want to copy anyway.
Anyway: thank you for the input, I'm going to try and replicate it and see how we can resolve this.
Shouldn't we revert this nice to have feature so that the core feature of Ray can be used?
It's better to re-submit the feature again in the future with better tests etc.
Just to elaborate on what happens:
- You check for recursion by doing print_r.
- print_r uses __debugInfo so it redacts stuff I know will be recursive because I didn't want any of that in my dumps anyway
- print_r doesn't have RECURSION thanks to that in itself, which results in isRecursive() === false
- var_export doesn't use the __debugInfo so it, for some weird reason, which I guess is too-deep-recursion which PHP itself doesn't handle well and therefore falls into the recursion trap.
I understand this could be even fixed on my side, but since the recursion is in a library and a property I use in BaseModel, there's no way to fix this on my side.
Anyway, I think it would be a good idea to even have the ability to switch off this feature as I can imagine the print_r itself on top of var_export can be memory and time consuming and sometimes older version of ray itself slow down the tests a lot if I have ray open (and pausing unfortunatelly doesn't work - I have to close ray for it to be fast again)
I was able to replicate scenario's that triggered the problems that were mentioned. I now added a more robust implementation to log variables.
As far as my own test scenario's go this seems to resolve all issues. It has been added to release 1.37.6.
In the future we might add some extra options to skip exporting these variables for when you want things to be faster like in tests.
I can confirm this resolved the issue. Thank you! Although, is there a way to force the depth to be deeper?
Because
- I can override LogPayload
- I can override PayloadFactory to return my LogPayload
- I would have to override Ray.php and copy all of it excluding the
$payloads = PayloadFactory::createForValues($arguments);
which would be a different (my) PayloadFactory.
I kinda like the clipboard feature, but hitting depth 5 is pretty easy a lot of times:
App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper#1
(
[App\Lead\Manager\LeadHandlerUtils\CascadeOfferItemsGrouper:lastDistributionType] => 'exclusive'
[cascadeOfferItemGroups] => Illuminate\Support\Collection#2
(
[*:items] => [
0 => App\Collections\CascadeOfferItemsCollection#3
(
[*:items] => [
0 => App\Models\CascadeOfferItem(...),
]
[*:escapeWhenCastingToString] => false
),
1 => App\Collections\CascadeOfferItemsCollection#4
(
[*:items] => [
0 => App\Models\CascadeOfferItem(...),
]
[*:escapeWhenCastingToString] => false
),
2 => App\Collections\CascadeOfferItemsCollection#5
(
[*:items] => [
0 => App\Models\CascadeOfferItem(...),
1 => App\Models\CascadeOfferItem(...),
]
[*:escapeWhenCastingToString] => false
),
3 => App\Collections\CascadeOfferItemsCollection#6
(
[*:items] => [
0 => App\Models\CascadeOfferItem(...),
]
[*:escapeWhenCastingToString] => false
),
]
[*:escapeWhenCastingToString] => false
)
)
have the same problem on 1.32, all I did was throw an exception, and log the exception with ray.
Edit: when I set always_send_raw_values => true
I was able to get rid of the memory error
I am on 1.33.0 on laravel-ray and 1.37.7 on ray itself. Still happens on that version?
Dear contributor,
because this issue seems to be inactive for quite some time now, I've automatically closed it. If you feel this issue deserves some attention from my human colleagues feel free to reopen it.