What Does TypeError: Argument Must Be of Type String, Null Given Mean?
An error such as TypeError: Argument #1 must be of type string, null given occurs when a function or method declares a parameter of type string but actually receives null. This is not a problem with the string itself or a PHP malfunction: the interpreter is reporting a type contract violation. The practical task is not to hide the exception, but to find where the required string value was lost or never assigned.
A typical example:
function normalizeEmail(string $email): string
{
return strtolower(trim($email));
}
$email = $_POST['email'] ?? null;
$result = normalizeEmail($email);
If the email field is missing from the request, the variable receives null, and the call ends with a TypeError before the function body is executed.
How to Read the Error Message
The full message usually includes the function name, argument number, expected and actual types, and the file and line where the call occurred. It is usually best to start the investigation at the call site rather than at the method declaration.
| Message fragment | What it indicates |
|---|---|
| Argument #1 | The problem is in the first argument passed to the function |
| must be of type string | The signature requires a string |
| null given | At runtime, null was passed |
| called in ... on line ... | The location where the invalid call was made |
If the exception has passed through several application layers, inspect the stack trace from the top down until you reach the first file from your own project. Framework or library frames often only pass control along, while the source of the invalid value is located in a controller, service, form handler, or repository.
Step-by-Step Diagnosis
1. Check the Value Immediately Before the Call
Temporarily record the variable’s type and value. In a production application, it is safer to write diagnostic data to a log instead of displaying it to the visitor.
error_log('email type: ' . get_debug_type($email));
error_log('email is null: ' . ($email === null ? 'yes' : 'no'));
$result = normalizeEmail($email);
Do not log passwords, tokens, full payment details, or other secrets. For user-provided fields, the type, an empty-value indicator, and an operation identifier are often sufficient.
2. Find the Source of null
A null value usually appears in one of the following places:
- a missing array key or HTTP request parameter;
- a database field that allows NULL;
- a lookup method that did not find a record;
- an optional object property;
- the result of decoding or transforming input data;
- a variable assigned only in one branch of a condition.
Do not inspect only the last line. For example, the ?? null operator makes code shorter, but it does not turn a missing value into a valid string.
3. Determine the Business Meaning of the Parameter
Before fixing the code, decide whether the value is allowed to be absent. The method signature and program behavior depend on the answer:
- if the string is required, validate the data and stop the operation with a clear error;
- if the value is optional, the parameter should be nullable and the code must handle
null; - if an empty string is valid, it can be used as the default value, but only when that matches the application logic.
Automatically replacing every null with '' often hides a data problem. For an email address, file path, class name, or identifier, an empty string is usually just as invalid as null.
Practical Ways to Fix the Error
Option 1. Required Field: Validate Before the Call
For a required value, check its presence and format before passing it to a typed method.
$email = $_POST['email'] ?? null;
if (!is_string($email) || trim($email) === '') {
throw new InvalidArgumentException('Поле email обязательно');
}
$result = normalizeEmail($email);
This approach preserves the strict signature and raises the error at a clear application layer. In a web form, the exception is usually replaced with a validation error and the form is returned to the user.
Option 2. Optional Field: Use a Nullable Type
When the value may legitimately be absent, the method contract should reflect that.
function normalizeMiddleName(?string $name): ?string
{
if ($name === null) {
return null;
}
$name = trim($name);
return $name === '' ? null : $name;
}
A nullable signature does not eliminate the need for handling. It only allows null to be passed; the subsequent behavior must still be defined explicitly.
Option 3. Default Value
A default value is appropriate for optional settings and labels. Before applying one, make sure that an empty string does not change the meaning of the operation or turn the original problem into a different error.
Option 4. Fix the Database Data
If a nullable column should actually be required, fix both the PHP code and the stored data. First, find rows containing NULL, determine the correct value, update the records, and only then tighten the schema constraint. Do not apply NOT NULL before cleaning up the existing data.
SELECT id, email
FROM users
WHERE email IS NULL;
After the migration, the application should still validate input data: a database constraint protects storage integrity, but it does not replace clear error handling.
Errors When Working with Arrays and JSON
Missing Array Key
An isset() check returns false both for a missing key and for a key whose value is null. If these situations have different meanings, use array_key_exists().
$payload = ['name' => null];
var_dump(isset($payload['name'])); // false
var_dump(array_key_exists('name', $payload)); // true
Invalid JSON
After decoding incoming JSON, check for errors and validate the result structure before reading any fields.
try {
$data = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
throw new InvalidArgumentException('Некорректный JSON', 0, $e);
}
if (!is_array($data)) {
throw new InvalidArgumentException('Ожидался JSON-объект');
}
$name = $data['name'] ?? null;
if (!is_string($name) || trim($name) === '') {
throw new InvalidArgumentException('Поле name обязательно');
}
Why Type Casting Does Not Always Solve the Problem
The (string) $value construct converts null to an empty string. The TypeError disappears, but the data may still be invalid.
$email = (string) ($_POST['email'] ?? null);
$result = normalizeEmail($email);
This approach is acceptable only when an empty string is an officially supported result. For required fields, strict validation is preferable. You should also avoid suppressing errors with the @ operator: it does not restore missing data and makes diagnosis less transparent.
Verifying the Fix
After changing the code, test more than the successful scenario. The minimum test set should include:
- a valid non-empty string;
- a missing field;
- an explicit null value;
- an empty string and a whitespace-only string;
- a value of another type, such as an array or number;
- a database record containing NULL, if the data source allows it.
Quick Checklist
- open the file and call-site line shown in the stack trace;
- check the actual argument type with
get_debug_type(); - trace the value back to the request, database, or lookup method;
- decide whether the parameter is required, nullable, or has a default value;
- do not replace
nullwith an empty string without checking the business logic; - add validation at the system boundary;
- align the constraints in the PHP code with the database schema;
- test a missing field, null, an empty string, and an invalid type;
- remove temporary diagnostics or keep only safe logging.
A reliable TypeError fix preserves the method’s strict contract and eliminates the source of the invalid value. The error then becomes either controlled validation or correctly supported nullable behavior instead of being hidden by an arbitrary type cast.