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

Laravel throws InvalidArgumentException although Controller completes execution #5

Closed
ewajs opened this issue Dec 5, 2022 · 8 comments

Comments

@ewajs
Copy link

ewajs commented Dec 5, 2022

We have a Shopify App created with osiset/laravel-shopify. Sadly the original maintainer of our app is no longer at the company (nor did they left us with much documentation to our detriment). The rest of the team has experience with PHP and Laravel but sadly not much with Shopify itself so I apologize in advance if we're missing something on that end. I remain at your disposal to add any further information that might be needed.

Our production environment is currently working, but we're experiencing issues in staging and mainly locally trying to replicate the Dev Environment in order to continue development and maintenance but we're facing some errors likely on the laravel side.

The fact that we haven't made any code changes suggest to me that there might be some version conflicts that make it different in production than locally, however we're not able to determine whether this assumption is correct.

The error in the logs states that we're passing an int where a string should be given but this is somewhat weird to understand as it is the framework code itself that seems to not be passing in the correct data type which is the Shop ID in the database (that is correctly forwarded by the frontend to Laravel).

Expected Behavior

Development App starts normally once installed.

Current Behavior

App installs correctly, however the first (and any subsequent) launch fails while calling the /state endpoint.

Failure Information

There's a /state endpoint used to populate the initial state for the React Frontend. Logging at various parts in the controller method that is executed whenever the endpoint is called shows that everything works correctly up until the method returns. However on the frontend the response throws a 500 error and the laravel logs show that the public/index.php (required by the root server.php file) file throws an error while capturing the request.

This is the last line of "our" code (everything else in the stacktrace is framework/dependencies code) that throws the error

$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Kernel::class);

$response = tap($kernel->handle(
    $request = Request::capture() // This crashes
))->send();

$kernel->terminate($request, $response);

This is the stack trace logged in laravel.log provided below in the corresponding section.

Steps to Reproduce

Please provide detailed steps for reproducing the issue.

  1. Install the Development App in the Development store. Installation itself should be succesful. User is added to database
  2. Go to the App Page in the Development Store. Frontend will be served but the call to the /state endpoint will fail (I can include this code if it helps but it doesn't produce an error on itself).

Context

  • Package Version: v17.3.2 (same composer.lock in Production and Local) <- this still points to osiset/laravel-shopify I'm wondering whether we should update the dependency to point to this new maintained version or not.
  • Laravel Version: v8.83.26 (same composer.lock in Production and Local)
  • PHP Version: v8.1.10 (local) and v8.1.12 (prod)

Failure Logs

This is the laravel.log after an unsuccessful call to the /state endpoint. In here the 62 shown in the call to fromNative (ShopDomain::fromNative(62) reported on line #0 of the Stack Trace) is the Shop ID of the currently logged in shop. It's weird that it expects a string rather than an integer.

[2022-12-05 17:37:37] local.ERROR: Can only instantiate this object with a string. {"exception":"[object] (InvalidArgumentException(code: 0): Can only instantiate this object with a string. at /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/funeralzone/valueobjects/src/Scalars/StringTrait.php:49)
[stacktrace]
#0 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/osiset/laravel-shopify/src/Objects/Values/ShopDomain.php(89): Osiset\\ShopifyApp\\Objects\\Values\\ShopDomain::fromNative(62)
#1 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/osiset/laravel-shopify/src/Http/Middleware/IframeProtection.php(52): Osiset\\ShopifyApp\\Objects\\Values\\ShopDomain::fromRequest(Object(Illuminate\\Http\\Request))
#2 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Cache/Repository.php(391): Osiset\\ShopifyApp\\Http\\Middleware\\IframeProtection->Osiset\\ShopifyApp\\Http\\Middleware\\{closure}()
#3 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php(418): Illuminate\\Cache\\Repository->remember('frame-ancestors...', Object(Illuminate\\Support\\Carbon), Object(Closure))
#4 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(261): Illuminate\\Cache\\CacheManager->__call('remember', Array)
#5 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/osiset/laravel-shopify/src/Http/Middleware/IframeProtection.php(53): Illuminate\\Support\\Facades\\Facade::__callStatic('remember', Array)
#6 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Osiset\\ShopifyApp\\Http\\Middleware\\IframeProtection->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#7 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#8 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#9 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#10 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#11 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#12 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#13 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#14 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest(Object(Illuminate\\Http\\Request), Object(Illuminate\\Session\\Store), Object(Closure))
#15 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#16 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#17 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#18 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#19 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#20 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#21 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Routing/Router.php(723): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#22 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Routing/Router.php(698): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request))
#23 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Routing/Router.php(662): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route))
#24 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Routing/Router.php(651): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request))
#25 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request))
#26 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(128): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request))
#27 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#28 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#29 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#30 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#31 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#32 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#33 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#34 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#35 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#36 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#37 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/fruitcake/laravel-cors/src/HandleCors.php(52): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#38 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Fruitcake\\Cors\\HandleCors->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#39 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#40 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(167): Illuminate\\Http\\Middleware\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
#41 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
#42 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
#43 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))
#44 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/public/index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))
#45 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/server.php(21): require_once('/Users/ezequiel...')
#46 {main}
"} 

@tinhphantrong0612
Copy link
Contributor

It seems like you passing shop id in your database instead of shop domain into ShopDomain::fromNative().
It gonna be like ShopDomain::fromNative('your-shop-name.myshopify.com').
And the shop domain is retrieved from request from shop (query params or headers), for example: $request->get('shop'). So make sure you passing it right.

@ewajs
Copy link
Author

ewajs commented Dec 7, 2022

Hello!
Thank you very much for replying!
Sadly I don't think this is an issue on our codebase nor something we're able to change, if you look at the stack trace there's no reference to the codebase itself (besides the index.php entrypoint that ultimately crashes). It doesn't seem to be us who are passing in the wrong value. Moreover, I'm sharing here some NW Requests screenshots from the browser you can see that the request succeeds in Production but fails locally although both requests seem identical (besides the host).

Could it be some kind of version mismatch in which one version (prod) requires the ID and another (local) requires the domain in the fromNative call?

I'm testing further to see if I can find more information to provide.

Here are the production screenshots:
Prod
Prod2

Screenshots with the local app (connected via ngrok):
Local
Local2

@tinhphantrong0612
Copy link
Contributor

From your stack trace, I saw #1 /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/osiset/laravel-shopify/src/Http/Middleware/IframeProtection.php(52): Osiset\\ShopifyApp\\Objects\\Values\\ShopDomain::fromRequest(Object(Illuminate\\Http\\Request))
It seems like it happened there.
And in IframeProtection.php, at line 52, $this->shopQuery->getByDomain(ShopDomain::fromRequest($request));
Extract shop domain from request.
And in fromRequest in ShopDomain class, we can see there are the shop was extract from three DataSource, the GET/POST variable (That one passing in body), HEADER and Referer.
And in your request, there are shop in both body and in query params, and it could work differently on local and production environment.

There is a for loop at the end of the fromRequest method:

foreach ($options as $value) {
            $result = is_callable($value) ? $value() : $value;
            if ($result !== null) {
                // Found a shop
                return self::fromNative($result);
            }
        }

If you could put a log like this:

foreach ($options as $value) {
            $result = is_callable($value) ? $value() : $value;
            if ($result !== null) {
                // Found a shop
                \Log::info('Shop: ' . $result);
                return self::fromNative($result);
            }
        }

You can check the shop that was used.

And also, can I ask what the /state route are for?

@Kyon147
Copy link
Owner

Kyon147 commented Dec 8, 2022

As @tinhphantrong0612

It looks like the wrong value is being passed down and have you made any changes to how the auth works as it is strange that you are passing in the ID as most of the calls work by getting the shop from the domain as that is unique and tied to the shop.

The package won't pass the id, so it seems like you have some custom work to change the way the package is running for your React auth.

It does not seem to be a package issue as I can not replicate this on any of my apps or a new version spun up.

@Kyon147
Copy link
Owner

Kyon147 commented Dec 12, 2022

@ewajs - any update on this? I'll close this ticket for now, as it looks like it is a specific issue with a custom implantation but feel free to update us in here.

@Kyon147 Kyon147 closed this as completed Dec 12, 2022
@ewajs
Copy link
Author

ewajs commented Dec 12, 2022

Hi @Kyon147, I'm still trying to understand whether our developer did something custom regarding this react auth. Thanks to everyone for the debugging ideas and clarifications. I'll continue looking into this and will come back whenever I have a clearer picture. I'm okay with closing this issue for now. It does seem there's something non-standard on our end.

@rvibit
Copy link
Contributor

rvibit commented Dec 15, 2022

Hi @Kyon147, I'm still trying to understand whether our developer did something custom regarding this react auth. Thanks to everyone for the debugging ideas and clarifications. I'll continue looking into this and will come back whenever I have a clearer picture. I'm okay with closing this issue for now. It does seem there's something non-standard on our end.

I was also facing a similar issue after updating to this fork (17.3.3), for me, the issue was that when submitting any form the shop param is not being sent to the Billable middleware (although it was received in the verify.shopify middleware which gets called just before Billable middleware) to fix this I passed the currently auth user <input type="hidden" name="shop" value="{{ $shopDomain ?? Auth::user()->name }}"> as a hidden field with my form.

it's weird that shop param is removed before reaching to the Billable middleware , I haven't done more research so idk what was the reason but the issue was fixed with hidden field.

For your issue check if you can somehow pass shop URL instead of shop ID to the iframe middleware

@ewajs
Copy link
Author

ewajs commented Dec 19, 2022

@rvibit thanks for your input! I might try that next!

To add some new context. Indeed it seems my issue was upgrading versions. I've found that pinning v17.1.1 fixes the issues and the app install goes smoothly and starts up correctly.

Why the upgrade breaks it is currently beyond me, but just for now pinning the version will suffice to get these testing environments up and running. Once I get more acquainted I'll retry upgrading to latest version and try your solution as keeping an old, unsupported version is not a long-term option.

I'm guessing that in order to switch to this mantained version I will have to update my composer.json, right? It does not seem that packagist has now switched over to this repo for newer versions. Am I right in my assumption?

@Kyon147 Do you happen by any chance to have some insight into why this issue might be happening to me and @rvibit on this upgrade??

The last outstanding issue I have is that it still seems to not want to work locally (it does in our staging server). I've tried setting up Apache given that I see an .htaccess file that would otherwise be ignored if I started the artisan dev server. It still does not want to work. It throws the following error:

Call to undefined method Osiset\ShopifyApp\Util::useNativeAppBridge() (View: /Users/ezequielwajs/Repos/ArtPlacer/artplacer-shopify/vendor/osiset/laravel-shopify/src/resources/views/layouts/default.blade.php)

Screenshot 2022-12-19 at 5 17 52 PM

After some digging I think this is related to the autogenerated PHP files located in storage/framework/views. I've tried deleting those and the error disappears but the app never installs and just directs me to a page saying I should install it on a loop.

Could there be some cleanup/setup process I should have done when upgrading/reinstalling that I might have accidentally skipped to regenerate this (or other) files properly?

Thanks in advance for the help and advise.

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

4 participants