rootuser's avatar

Possible bug in Jetstream

Hi,

On a freshly set up Laravel project with Jetstream I got issues with the 'forgot password' function.

Sometimes I get an HTTP 500 error when sending the request. Nevertheless, the reset mail is sent to me. When I reload the page, the page is schown again with the message 'We have emailed your password reset link'.

I also get '519 - page expired' errors every once in a while, which I cannot understand at all.

Have any of you seen this problem before and perhaps even know what the problem could be? Thanks!

0 likes
9 replies
LaryAI's avatar
Level 58

It sounds like you're encountering intermittent server errors and session issues with your Laravel Jetstream application. Here are a few steps you can take to troubleshoot and potentially resolve the issue:

  1. Check the Logs: The first step should be to check the Laravel logs for any error messages. These logs are typically located in storage/logs/laravel.log. The error message associated with the HTTP 500 error should give you more insight into what's going wrong.

  2. Session Configuration: The '419 - page expired' error is often related to session issues, such as a mismatched CSRF token. Make sure your session configuration is correct in your .env file and config/session.php. Also, ensure that your application is able to write to the storage/framework/sessions directory.

  3. CSRF Token: Ensure that the CSRF token is included in your password reset form. Jetstream uses Livewire or Inertia.js, depending on your setup, and it should handle CSRF protection automatically. However, if you've made custom changes to the forms, double-check that the CSRF token is present.

  4. Cache and Configuration: Clear your application cache and re-cache the configuration. You can do this by running the following Artisan commands:

php artisan cache:clear
php artisan config:cache
  1. Dependencies: If you've recently updated your Laravel application or any dependencies, make sure that there are no compatibility issues. You can do this by checking the release notes for the packages you've updated.

  2. Mail Configuration: Since the reset email is being sent despite the error, it's unlikely that the mail configuration is the issue. However, it's still worth checking your .env file to ensure that your mail settings are correct.

  3. Environment: If you're only experiencing this issue in your production environment, make sure that the .env file on the server is configured correctly and that all environment-specific settings are appropriate.

  4. Update Packages: Ensure that you are using the latest version of Laravel and Jetstream. You can update your dependencies by running:

composer update
  1. Permissions: File permissions can sometimes cause unexpected issues. Ensure that the web server has the appropriate permissions to write to the storage and bootstrap/cache directories.

If none of these steps resolve the issue, you may want to provide more specific error messages or stack traces from your logs to get more targeted help. Remember to redact any sensitive information before sharing error logs publicly.

rootuser's avatar

Hello again, I have found the solution. There was a problem with the encryption key.

However, it was created correctly, which is why I could not interpret the corresponding error message in the log.

Finally I found the hint that a simple 'php artisan config:cache' might help. And yes, it does, at least in all attempts since then.

Yes, I probably could have thought of that earlier. Rookie mistake. Maybe this will help someone else.

Snapey's avatar
Snapey
Best Answer
Level 122

dont cache until you are in final production deployment. Caching should never be a 'fix'.

You will face a lot of head scratching if you cache in development

500 errors shoul always be investigated firstly in the log files

page expired errors WILL occur if you leave your site on a form for more than the session lifetime since when you come to use the form the csrf token will no longer be recognised and a 419 will be thrown

1 like
rootuser's avatar

Thank you for the clarification!

I have now disabled caching in my development environment by adding the following code to the cache stores configuration in config/cache.php file

'stores' => [
    //...
    'none' => [
        'driver' => 'null',
    ],
  ],

and then setting

CACHE_STORE=none

in the .env file.

I hope this helps someone.

rootuser's avatar

@Snapey Why on earth are you asking? :-D

You said: 'dont cache until you are in final production deployment.' Did I get that wrong? (Please assume that I am a Laravel beginner, if you are not already)

Did you mean I should not use

php artisan config:cache

?

But it solved my problem and I couldn't find any other solution. Do you have a better idea?

Snapey's avatar

@rootuser No. just run artisan config:clear. I didn't mean to disable all caching. That would be stupid because caching is a key ingredient in making your site performant. Its just that you trip yourself up if you cache config and routes in development by using config:cache or Route:cache or optimize

rootuser's avatar

In the meantime, I possibly found a real issue.

I tried to customize the ResetPassword notification following the documentation here: https://laravel.com/docs/11.x/verification#verification-email-customization

The documentation says: The closure will receive [...] the signed email verification URL. But that is not the case.

ResetPassword::toMailUsing(function (object $notifiable, string $url) {
   return (new MailMessage)
      ->subject(__('some subject'))
      ->line(__('text'))
      ->action(__('button text'), $url)
      ->line(__('further text'));
});

With this code inside boot() function in the AppServiceProvider, the Link in the email only consists of the token, like '0ac3956ad99ddaff7786c6ecd83febc4d0e9fef0a36e83fdfa6150fbcd8d7cc4'.

When I remove the code, I get complete URLs again, like

'http://domain.com/reset-password/0ac3956ad99ddaff7786c6ecd83febc4d0e9fef0a36e83fdfa6150fbcd8d7cc4'?email=users%40domain.com'.

Of course, I might use

->action(__('button text'), config('app.url') . '/reset-password/' . $url)

but this is not how it is meant to be, is it?

Please or to participate in this conversation.