Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught ErrorException: var_export does not handle circular references #832

Closed
genesiscz opened this issue Sep 2, 2023 · 13 comments
Closed
Assignees

Comments

@genesiscz
Copy link

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.
image
image

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
@bartbrinkman
Copy link

Downgrading to 1.37.2 worked for me.

@timvandijck
Copy link
Member

@genesiscz @bartbrinkman I added an extra check for recursiveness before doing the var_export. Could you give 1.37.5 a try?

@crynobone
Copy link
Contributor

@timvandijck Still broken with 1.37.5

CleanShot 2023-09-07 at 08 30 26

@genesiscz
Copy link
Author

@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?

@genesiscz
Copy link
Author

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

@timvandijck
Copy link
Member

@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.

@crynobone
Copy link
Contributor

crynobone commented Sep 7, 2023

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.

@genesiscz
Copy link
Author

genesiscz commented Sep 7, 2023

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)

@timvandijck
Copy link
Member

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.

@genesiscz
Copy link
Author

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
    )
)

Ray
image

@ZebTheWizard
Copy link

ZebTheWizard commented Sep 13, 2023

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

@genesiscz
Copy link
Author

I am on 1.33.0 on laravel-ray and 1.37.7 on ray itself. Still happens on that version?

@spatie-bot
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants