sickn33/agentic-awesome-skills · error · Error

User not found

Error message

User not found

What it means

The second throw in fp-ts-errors' example: db.find(id) returned nothing for a well-formed id. The skill's point is that callers cannot see this failure in the type and must either wrap every call in try/catch or risk runtime crashes.

Source

Thrown at skills/fp-ts-errors/SKILL.md:38

The core idea: **Errors are just data**. Instead of throwing them into the void and hoping someone catches them, return them as values that TypeScript can track.

---

## 1. Stop Throwing Everywhere

### The Problem with Exceptions

Exceptions are invisible in your types. They break the contract between functions.

```typescript
// What this function signature promises:
function getUser(id: string): User

// What it actually does:
function getUser(id: string): User {
  if (!id) throw new Error('ID required')
  const user = db.find(id)
  if (!user) throw new Error('User not found')
  return user
}

// The caller has no idea this can fail
const user = getUser(id) // Might explode!
```

You end up with code like this:

```typescript
// MESSY: try/catch everywhere
function processOrder(orderId: string) {
  let order
  try {
    order = getOrder(orderId)
  } catch (e) {
    console.error('Failed to get order')
    return null

View on GitHub (pinned to 58d857988f)

Solutions

  1. Return Either/Error union from getUser so absence is a typed value (the skill's core fix)
  2. Handle the not-found case explicitly at the caller (render 404, clear session) rather than catching a generic Error
  3. Add tenant/scope filters so the lookup queries the right data set

Example fix

// before
const user = db.find(id)
if (!user) throw new Error('User not found')
return user

// after
type DomainError = { _tag: 'UserNotFound' } | { _tag: 'InvalidId' }
const getUser = (id: string): E.Either<DomainError, User> => {
  if (!id) return E.left({ _tag: 'InvalidId' })
  const user = db.find(id)
  return user ? E.right(user) : E.left({ _tag: 'UserNotFound' })
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const user = getUser(id)
} catch (e) {
  if (e instanceof Error && e.message === 'User not found') {
    // 404 / clear stale session
  } else throw e
}

Prevention

When it happens

Trigger: Calling getUser with a syntactically valid id that has no row: deleted users, expired sessions referencing purged accounts, or lookups against the wrong database/environment.

Common situations: Session stores holding user ids after account deletion; multi-tenant systems queried without tenant context; 404 handling missing so this throw becomes an unhandled 500.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of sickn33/agentic-awesome-skills@58d857988f (2026-08-26). Data as JSON: /api/errors/3d5b7fae5617fe44. Report an issue: GitHub.