The "TypeError: Argument must be of type" error happens when a PHP function or method receives a value that doesn't match the type declared in its parameter.

A typical error looks like:

TypeError: foo(): Argument #1 ($user) must be of type User, null given

You may also see:

TypeError: Argument #1 must be of type string, int given

or:

TypeError: Argument #2 must be of type array, null given

This error is common in modern PHP applications and Laravel projects because PHP enforces declared parameter types more strictly.

In this guide, you'll learn why this error happens and how to fix it.

Why Does "Argument Must Be of Type" Happen?

Consider this function:

function greet(string $name)
{
    return "Hello " . $name;
}

The $name parameter must be a string.

This works:

greet('Ali');

But this can cause a TypeError:

greet(123);

The function expects a string, but the value being passed doesn't match the expected type.

The exact solution depends on what value your application is actually receiving.

Fix 1: Check the Value You're Passing

First, find the line mentioned in the TypeError.

For example:

TypeError: greet(): Argument #1 ($name) must be of type string, null given

This tells you:

  • The function is greet()

  • The problem is argument #1

  • The parameter is $name

  • PHP expected a string

  • Your code passed null

Check the value before passing it:

$name = $user['name'] ?? '';

greet($name);

Don't blindly change the function type until you understand why the wrong value is being passed.

Fix 2: Handle Null Values

One of the most common Laravel causes is a value being null.

Example:

$user = User::find($id);

sendEmail($user->email);

If the user doesn't exist, $user is null and the code can fail before reaching the function.

Use:

$user = User::findOrFail($id);

sendEmail($user->email);

Or check the result:

$user = User::find($id);

if ($user) {
    sendEmail($user->email);
}

If the function legitimately accepts null, make the parameter nullable:

function sendEmail(?string $email)
{
    // ...
}

The ?string means the parameter can contain either a string or null.

Fix 3: Check Laravel Request Data

A common mistake is assuming request input always has the expected type.

For example:

function findUser(int $id)
{
    // ...
}

findUser(request('id'));

If the request doesn't contain id, you may pass null.

Use validation:

$request->validate([
    'id' => ['required', 'integer'],
]);

Then:

findUser((int) $request->id);

Validation is preferable to simply casting everything because it ensures the incoming data is actually valid.

Fix 4: Check Database Results

Laravel methods such as find() and first() can return null.

Example:

$user = User::where('email', $email)->first();

processUser($user);

If no user exists, $user is null.

If your method requires a User object:

function processUser(User $user)
{
    // ...
}

use:

$user = User::where('email', $email)->firstOrFail();

processUser($user);

This makes the failure explicit instead of passing null into a method that requires a User.

Fix 5: Check Argument Order

Sometimes the values are correct but passed in the wrong order.

Example:

function createUser(string $name, int $age)
{
    // ...
}

Incorrect:

createUser(25, 'Ali');

PHP expects:

Argument #1 → string
Argument #2 → int

but receives:

Argument #1 → int
Argument #2 → string

Correct:

createUser('Ali', 25);

Check the function definition and compare every argument in the same order.

Fix 6: Use the Correct Array Type

Suppose your method expects an array:

function processUsers(array $users)
{
    // ...
}

This is valid:

processUsers([
    'Ali',
    'John',
]);

But this can fail:

processUsers(null);

If null is a valid possibility, either handle it before calling the method:

processUsers($users ?? []);

or explicitly allow null:

function processUsers(?array $users)
{
    // ...
}

Use the second approach only when null actually has meaningful behavior in your application.

Fix 7: Check Object Types

A method may require a specific class:

function updateUser(User $user)
{
    // ...
}

Passing another object:

$post = new Post();

updateUser($post);

causes a TypeError because Post is not a User.

Pass the expected object:

$user = User::findOrFail($id);

updateUser($user);

Fix 8: Check Return Types

The same problem can happen with return values.

Example:

function getUserName(): string
{
    return null;
}

This causes a TypeError because the function promises to return a string.

If null is valid:

function getUserName(): ?string
{
    return null;
}

Or return a valid string:

function getUserName(): string
{
    return '';
}

Your declared return type should match what the function can actually return.

Fix 9: Check Laravel Model Relationships

Relationships can return null when a related record doesn't exist.

Example:

function showProfile(Profile $profile)
{
    // ...
}

showProfile($user->profile);

If the user has no profile, $user->profile is null.

Check first:

if ($user->profile) {
    showProfile($user->profile);
}

Or use a required relationship/record lookup when the relationship must exist.

Fix 10: Check PHP Type Declarations

Your function may have a strict type declaration:

function calculateTotal(float $price, int $quantity)
{
    return $price * $quantity;
}

Make sure you're passing appropriate values:

calculateTotal(99.99, 2);

If the application receives data from forms, APIs, or databases, validate and normalize it before passing it to strongly typed methods.

How to Find the Exact Cause

The error message usually contains everything you need.

For example:

TypeError: UserService::find(): Argument #1 ($id)
must be of type int, string given

Look at:

1. The function or method

UserService::find()

2. The argument number

Argument #1

3. The expected type

int

4. The actual type

string

This tells you exactly what needs investigation.

Debug the Value Before Passing It

If you're unsure what your code is receiving, inspect the value:

dd($value);

or:

dump($value);

You can also check its type:

dd(gettype($value), $value);

For objects:

dd(get_class($value));

Once you know the actual value and type, the correct fix becomes much easier to identify.

Don't Just Remove the Type Declaration

You may find advice suggesting you change:

function processUser(User $user)

to:

function processUser($user)

This removes the immediate TypeError, but it may simply hide the underlying problem.

If the method genuinely requires a User, keep the type declaration and fix the value being passed to it.

Strong typing helps catch bugs early.

Final Checklist

When you see:

TypeError: Argument must be of type

check:

  • ✓ Read the complete error message

  • ✓ Identify the argument number

  • ✓ Check the expected type

  • ✓ Check the actual value being passed

  • ✓ Check for unexpected null values

  • ✓ Check Laravel find() and first() results

  • ✓ Validate request input

  • ✓ Check argument order

  • ✓ Check model relationships

  • ✓ Verify return type declarations

  • ✓ Keep type declarations unless the parameter genuinely supports another type

The important part is not simply changing the expected type. Find out why your code is receiving the wrong value in the first place.

If your PHP or Laravel application is showing a TypeError and you're unsure what is causing it, send me the complete error message and the relevant function or method. I can help identify the exact mismatch and the correct fix.