Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

twoarmtom's avatar

Sending email during Import: No query results for model [App\User]

I have the following Import function:

public function collection(Collection $rows)
    {
        foreach($rows as $row)
        {
            if(User::where('email', $row['email'])->first() == null)
            {
                $user = User::create([
                    //
                'name'     => $row['name'],
                'email'    => Str::lower($row['email']), 
                'password' => Hash::make(Str::random(10)),
                ]);
                $role = $row['role'];
                $location = $row['location'];
            
                $user->roles()->attach($role);
                $user->hospital()->attach($location);
                $token = app('auth.password.broker')->createToken($user);

                Mail::to($user)->queue(new NewAccount($user, $token));
            }
            sleep(2);
        }

    }

In my local environment this works perfect. In production the email part of this loop is failing (and I know emails work, I've tested them with password resets etc.).

In Laravel Horizon it shows:

ID 111

Queue default

Tags App\User:207

Failed At 2021-03-04 15:18:16

And it gives this error:

Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\User]

The NewAccount Mail is:

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\User;

class NewAccount extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;

        
    /**
     * Create a new message instance.
     *
     * @return void
     */
    
    public $user;
    public $token;
    public function __construct(User $user, $token)
    {
        //
        $this->user = $user;
        $this->token = $token;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.setpassword');
    }
}

The only difference between local and production that I can think of is the use of Redis for queue. In my local environment I'm not using Redis.

Any ideas why this may be failing? I should add that this mail class is used for normal registration and works without issue.

0 likes
8 replies
Snapey's avatar

before the Mail, try adding $user->refresh();

twoarmtom's avatar

Just the first one goes through, then the same failed message. I'm testing it with 4 users.

twoarmtom's avatar

Interestingly enough, I went in a tested it again (after deleting users) and it worked, but then I tried again (after deleted users again) and it failed with the same issue as before. Not sure why it is being so inconsistent.

twoarmtom's avatar

I used the sleep(2) function because of limits with Mailtrap, and I wasn't using a queue worker in my local environment. I just realized that if I remove the sleep(2) function it works in production.

My worry is that there may be issues with the mail server if I import hundred of users and there's no pause between each user.

Is this worry I have avoided by using the redis queue? Sorry if this is a dumb question.

Snapey's avatar
Snapey
Best Answer
Level 122

is this part of laravel excel import?

The entire import is automatically wrapped in a database transaction, that means that every error will rollback the entire import. When using batch inserts, only the current batch will be rollbacked.

If so, then what is happening is that the queue is starting the job but the transaction has not yet been committed to the database, so outside the function you have here, these users do not exist.

https://docs.laravel-excel.com/3.1/imports/validation.html#disable-transactions

or delay your mail jobs until after the import is complete.

twoarmtom's avatar

Yes, it is part of the import, I wondered if it was maybe because the sleep(2) function would prevent the user import from being complete before the Mail would be attempted, so the user wasn't added yet. When I removed the sleep(2) function it seemed to work, maybe because the test import is only 4 users and it quickly made it through the loop before the queue attempted to send the email. Might not be so lucky with a larger import so I like your idea of delay.

Would the best way to use a delay be to change the queue function to later like so?

$when = now()->addMinutes(5);

Mail::to($user)->later($when, new NewAccount($user, $token));

Thank you for your help and advice, much appreciated!

Snapey's avatar

either delay the queued emails as you have shown, or send the emails after the import by running a seperate query and mailing all newly imported users

1 like
twoarmtom's avatar

Thank you, the delay seems to be working. I really appreciate your time.

Please or to participate in this conversation.