PHP 8.5 introduces a small but useful addition to the language: the #[\NoDiscard] attribute. It allows developers to identify functions and methods whose return values should not be silently ignored. The feature addresses a familiar problem in application development, where an operation succeeds partially, returns important information, and the calling code simply moves on.
Released with PHP 8.5 on November 20, 2025, NoDiscard is not a replacement for exceptions, type declarations, or static analysis. It adds a runtime warning to a situation that is otherwise easy to overlook. For library maintainers and application developers designing APIs around validation, batch processing, and immutable objects, this can be particularly useful.
The Problem with Ignored Results
Consider a function that processes multiple records and returns a summary of what succeeded and what failed. An application might call it like this:
validateImport($records);
// Continue processing...
There is nothing inherently invalid about this code. The function executes, and PHP does not normally require callers to inspect its return value. However, if some records failed validation, the application may continue without noticing.
We could redesign the function to throw an exception whenever it encounters an invalid record. But that is not always appropriate. Batch operations often need to process every item and return a collection of individual errors rather than interrupting the entire operation.
This is the situation NoDiscard is intended to address: an important result exists, and ignoring it is probably a programming mistake.
How NoDiscard Works in PHP 8.5
The attribute can be applied directly to a function or method declaration:
[email protected]');
On PHP 8.5, the final call emits a warning because its result is discarded. The function still executes, and the warning does not automatically become an exception.
The attribute also accepts an optional message that explains why the result matters:
#[\NoDiscard(
'Check the validation result before proceeding'
)]
function validateEmail(string $email): bool
{
return filter_var(
$email,
FILTER_VALIDATE_EMAIL
) !== false;
}
The custom message appears as part of the warning, providing useful context for developers diagnosing the issue.
A Practical Example: Import Validation
Let’s build a small import validator. Rather than throwing an exception for every invalid row, it returns a report containing accepted email addresses and validation errors. This is useful when an application needs to review an entire input file before deciding whether to proceed.
errors !== [];
}
}
#[\NoDiscard(
'Inspect rejected records before importing'
)]
function validateImport(array $rows): ImportReport
{
$accepted = [];
$errors = [];
foreach ($rows as $index => $row) {
$email = $row['email'] ?? null;
if (
!is_string($email)
|| filter_var(
$email,
FILTER_VALIDATE_EMAIL
) === false
) {
$errors[$index] = 'Invalid email';
continue;
}
$accepted[] = $email;
}
return new ImportReport(
accepted: $accepted,
errors: $errors,
);
}
$records = [
['email' => '[email protected]'],
['email' => 'invalid-email'],
['email' => '[email protected]'],
];
$report = validateImport($records);
if ($report->hasErrors()) {
foreach ($report->errors as $index => $error) {
echo "Row {$index}: {$error}\n";
}
}
echo count($report->accepted);
echo " valid records\n";
Our example accepts two addresses and reports one invalid record. The caller explicitly receives and examines the result, so no NoDiscard warning is produced.
Now imagine a developer accidentally replaces the reporting logic with a standalone call:
validateImport($records);
PHP 8.5 warns that the returned report has been discarded. This does not guarantee correct business logic, but it makes one class of oversight visible during development and testing.
Intentionally Ignoring a Result
Sometimes ignoring a return value is deliberate. PHP 8.5 introduces a corresponding (void) construct to express that decision:
(void) validateImport($records);
This suppresses the NoDiscard warning while making the caller’s intention explicit. Unlike ordinary type casts, (void) is a statement that discards the expression’s value; it cannot be used as part of a larger expression.
For code that must also run on PHP 8.4 or earlier, assigning the result to a temporary variable provides a compatible alternative:
$_ = validateImport($records);
The attribute itself can be present in PHP 8.0 through 8.4 code, but it has no built-in NoDiscard behavior on those versions. The (void) syntax specifically requires PHP 8.5.
Where NoDiscard Makes Sense
Not every function needs this attribute. Adding it indiscriminately would make warnings less meaningful and could encourage developers to suppress them without examining the underlying issue.
The best candidates are functions whose returned values communicate information that is essential to correct operation. Examples include batch import reports, validation results, immutable object transformations, and operations returning partial-failure information.
Immutable APIs are an especially interesting case. A method may return a new object rather than modifying the existing one. If a developer invokes the method and discards its result, the expected change never reaches the rest of the application.
By contrast, a function used primarily for its side effects may not benefit from NoDiscard, particularly when its result is merely informational or optional.
Important Limitations
NoDiscard is a runtime diagnostic mechanism, not a compile-time guarantee. Whether developers see its warnings depends on their error-reporting configuration and development workflow. It also does not verify that the returned value was interpreted correctly; assigning a result to an unused variable is not the same as handling it properly.
There is another detail library authors should consider: the attribute is attached to a particular method declaration. Marking an interface or abstract method does not automatically cause warnings for an unannotated implementation. Likewise, overriding methods do not automatically inherit this behavior. The PHP manual documents these distinctions explicitly.
For existing projects, introducing the attribute gradually is preferable to annotating an entire API at once. Start with methods that have produced real bugs or where ignoring a result creates a meaningful risk.
Conclusion
PHP 8.5’s NoDiscard attribute is a modest addition with practical implications for API design. It gives developers a way to communicate that a return value matters and provides an immediate warning when that expectation is ignored.
It will not eliminate application bugs or replace careful testing. Its value comes from highlighting an otherwise silent mistake, particularly in code where returning structured results is more appropriate than throwing exceptions.
For teams adopting PHP 8.5, NoDiscard is worth considering wherever important results can disappear unnoticed between one operation and the next.
Official References
Related
php-8-5-nodiscard-catching-ignored-return-values-before-they-become-production-bugs

