Ffile2fix
Sign in Get started

How to fix "TypeError: Argument must be of type" in PHP

PHP Fatal error:  Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, null given in /home/user/public_html/wp-content/themes/mytheme/inc/menu.php:31

A function expected one type of value but received another, and PHP 8 throws a TypeError instead of guessing. Many built-in functions that only warned in PHP 7 now throw, such as count() on null. The message tells you which argument, the expected type and what was actually passed.

Also appears as: Uncaught TypeError: strlen(): Argument #1 ($string) must be of type string, array given · TypeError: App\Service\Price::__construct(): Argument #1 ($amount) must be of type int, string given, called in /home/user/app/src/Cart.php on line 12 · Uncaught TypeError: implode(): Argument #2 ($array) must be of type ?array, string given · Uncaught TypeError: array_merge(): Argument #1 must be of type array, null given

Common causes

  • Passing null where an array or string is required, often from a failed lookup
  • count(), implode() or array_merge() used on a value that is not an array
  • Numeric strings from forms or databases passed to int parameters under declare(strict_types=1)
  • Old plugins or themes written for PHP 7 now running on PHP 8
  • Argument order changed, for example implode() with the array first and glue second (removed in PHP 8)
  • A typed property or parameter receiving data from an API in a different format

How to fix it

  1. Read the three parts of the message. Note the function name, the argument number and name, and the "X given" type. The "called in" path shows where the wrong value came from.
  2. Trace the bad value. Go to the calling line and find where that variable is set. If it is null, the earlier lookup found nothing; handle that case there.
  3. Add a safe default. Use count($items ?? []) or (array) casts carefully, or set defaults where the data is loaded, so the function always gets the type it needs.
  4. Convert input explicitly. Form and database values are strings. Cast them, for example (int) $_POST['qty'], after validating them with filter_var() or is_numeric().
  5. Update or patch old code. If the error is in a plugin or theme, update it. For your own code, fix PHP 8 changes such as the implode() argument order and count() on non-arrays.

Validate and cast values before passing them

$items = get_post_meta($id, 'items', true) ?: [];
echo count($items);

$qty = filter_var($_POST['qty'] ?? null, FILTER_VALIDATE_INT);
if ($qty === false) {
    throw new InvalidArgumentException('Invalid quantity');
}
$cart->add($productId, $qty);

How to stop it happening again

  • Use type declarations everywhere so errors show up early in development
  • Validate and cast all request data at the edge of your app
  • Test plugins and themes on PHP 8 staging before upgrading live
  • Run PHPStan at a level that checks argument types

Frequently asked questions

Why did count() stop working on null?

In PHP 7.2 count(null) only raised a warning. Since PHP 8.0 it throws a TypeError, so code that relied on it returning 0 now crashes.

What does declare(strict_types=1) change?

Without it, PHP converts compatible scalar values, such as "5" to 5. With it, the types must match exactly, so a numeric string passed to an int parameter throws.

Can I catch the TypeError?

Yes, with try { ... } catch (TypeError $e) { ... }. It is better to fix the value, but catching is useful when handling untrusted data.