cakephp/cakephp · error · RecordNotFoundException
Record not found in table
Error message
Record not found in table `%s`.
What it means
SelectQuery::firstOrFail() executes the query and throws Cake\Datasource\Exception\RecordNotFoundException when no row matches. The library throws it to give callers a fail-fast semantic for 'this record must exist'. The table name in the message comes from the query's repository via getTable().
Solutions
- Wrap the call in try/catch for RecordNotFoundException and handle the missing-record case (404 response, fallback)
- Verify the WHERE conditions and values actually match rows (log the SQL, run it manually)
- Check the row isn't excluded by a status/deleted scope on the query
- If empty results are legitimate, use first() instead of firstOrFail() and null-check
Example fix
// before
$article = $articles->find()->where(['slug' => $slug])->firstOrFail();
// after
try {
$article = $articles->find()->where(['slug' => $slug])->firstOrFail();
} catch (RecordNotFoundException $e) {
throw new NotFoundException(__("No article with slug {0}", $slug));
} Defensive patterns
Strategy: try-catch
Validate before calling
// before
$count = $query->count(); // or: $exists = $query->count() > 0;
if ($count === 0) { /* handle empty */ } Type guard
$entity = $query->first();
if ($entity === null) { /* not found */ } Try / catch
use Cake\Datasource\Exception\RecordNotFoundException;
try {
$entity = $query->firstOrFail();
} catch (RecordNotFoundException $e) {
// return 404 / fallback entity
} Prevention
- Prefer first() with a null-check when absence is a normal state
- Log or include the query conditions when converting to a 404 for debuggability
- Test lookups against realistic fixtures including soft-deleted rows
- Cast/normalize key values (string vs int) before building WHERE conditions
When it happens
Trigger: Calling ->firstOrFail() on a SELECT query whose WHERE conditions match zero rows — e.g. a wrong primary key value, a soft-delete/status filter excluding the row, or conditions built from unsanitized/unexpected input.
Common situations: Controller edit/view actions doing $articles->get($id) style lookups replaced by find()->where([...])->firstOrFail(); REST APIs returning 404; fixtures/seed data missing so lookups in tests fail; case-sensitivity or type mismatches (string '1' vs int 1) in the WHERE clause.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Node ` ` was not found in the tree.
- Record not found in table
- Record not found in table
- All primary key value(s) are needed for updating
- Argument 2 is expected to have a `repository` key that…
AI-assisted analysis of cakephp/cakephp@1128eba9b0 (2026-09-12).
Data as JSON: /api/errors/c9549388be3f8a82.
Report an issue: GitHub.
Appendix: source
Thrown at src/ORM/Query/SelectQuery.php:607
if ($this->_dirty) {
$this->limit(1);
}
return $this->all()->first();
}
/**
* Get the first result from the executing query or raise an exception.
*
* @throws \Cake\Datasource\Exception\RecordNotFoundException When there is no first record.
* @return TSubject The first result from the ResultSet.
*/
public function firstOrFail(): mixed
{
$entity = $this->first();
if (!$entity) {
$table = $this->getRepository();
throw new RecordNotFoundException(sprintf(
'Record not found in table `%s`.',
$table->getTable(),
));
}
return $entity;
}
/**
* Returns an array with the custom options that were applied to this query
* and that were not already processed by another method in this class.
*
* ### Example:
*
* ```
* $query->applyOptions(['doABarrelRoll' => true, 'fields' => ['id', 'name']);
* $query->getOptions(); // Returns ['doABarrelRoll' => true]
* ```View on GitHub (pinned to 1128eba9b0)