Skip to content

findOrFail

Like find, but throws ModelNotFoundException when no row matches. Pass an array of ids to require all of them to exist.

Signature

ts
FedacoBuilder<T>.findOrFail(id: string | number, columns?: string[]): Promise<T>
FedacoBuilder<T>.findOrFail(ids: any[], columns?: string[]): Promise<T[]>

Parameters

NameRequiredDescription
idPrimary-key value, or array of values.
columnsoptionalColumns to select. Defaults to ['*'].

Returns

The model (or array of models). Throws if any requested id is missing.

Behaviour Difference From find

InputfindfindOrFail
Scalar, foundmodelmodel
Scalar, missingundefinedthrows ModelNotFoundException
Array, all foundarrayarray
Array, partialpartial arraythrows ModelNotFoundException
Array, none found[]throws ModelNotFoundException

Real-World Use Cases

1. HTTP 404 mapping

findOrFail lets you skip the if (!user) throw 404 boilerplate:

ts
import { ModelNotFoundException } from '@gradii/fedaco';

app.get('/users/:id', async (req, res) => {
  try {
    const user = await User.createQuery().findOrFail(req.params.id);
    res.json(user);
  } catch (e) {
    if (e instanceof ModelNotFoundException) {
      res.status(404).end();
      return;
    }
    throw e;
  }
});

Wrap the try/catch in a global error handler so your route handlers stay clean.

2. Required relation traversal

ts
const post = await Post.createQuery().findOrFail(postId);
const author = await User.createQuery().findOrFail(post.author_id);

If either record is missing, the request fails fast instead of silently dereferencing undefined.

3. Inside a transaction (atomic delete)

ts
await db().transaction(async (tx) => {
  const user = await User.createQuery(tx).findOrFail(userId);
  await user.Delete();
});

The transaction rolls back if the user wasn't found, leaving prior writes untouched.

4. Bulk: require all ids

ts
// All four IDs must exist; otherwise throws.
const team = await User.createQuery().findOrFail([1, 2, 3, 4]);
console.log(team.length); // 4 (or throws)

This is the right call when partial success would be a bug — e.g. assigning a permission set where every user must exist.

5. Project columns

ts
const user = await User.createQuery().findOrFail(42, ['id', 'email']);

Common Pitfalls

  • The error is a thrown Error, not a Promise rejection callback — make sure your async handler awaits the call so the rejection surfaces.
  • Bulk semantics differ from find: find([1, 99]) quietly returns [user1]; findOrFail([1, 99]) throws. Pick the one that matches your intent.
  • Don't catch and ignore. If you don't actually want the failure, use find or findOrNew.

See Also

Released under the MIT License.