sickn33/agentic-awesome-skills · error · Error

ID required

Error message

ID required

What it means

Part of the hidden-failure-mode example in the fp-errors skill (skills/fp-errors/SKILL.md:43). It is thrown synchronously by getUser when called with an empty or falsy id, despite the signature function getUser(id: string): User promising an unconditional User. The doc uses it to show why unchecked exceptions make signatures lie.

Source

Thrown at skills/fp-errors/SKILL.md:43

- You need to replace exception-heavy code with `Either` or `TaskEither`.
- The task involves validation, domain errors, or clearer error contracts in TypeScript.
- You want pragmatic fp-ts error-handling guidance for real application code.

---

## 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) {

View on GitHub (pinned to 58d857988f)

Solutions

  1. Validate and reject empty ids at the system boundary (request parsing) before calling getUser
  2. Change the signature to make failure explicit: return Either of an error or User, or throw a typed ValidationError the caller must acknowledge
  3. Use a branded non-empty-string type for id parameters

Example fix

// before
function getUser(id: string): User {
  if (!id) throw new Error('ID required')
  // ...
}

// after
const getUser = (id: NonEmptyString): E.Either<UserError, User> =>
  pipe(
    db.find(id),
    E.fromNullable({ tag: 'not-found' } as const)
  )
Defensive patterns

Strategy: validation

Validate before calling

const isNonEmpty = (s: string): boolean => s.trim().length > 0
if (!isNonEmpty(id)) {
  return badRequest('id must be a non-empty string')
}

Type guard

type NonEmptyString = string & { readonly brand: unique symbol }
const nonEmpty = (s: string): s is NonEmptyString => s.trim().length > 0

Prevention

When it happens

Trigger: Calling getUser with an empty string or a nullish value cast to any: any falsy id fails the if (!id) guard before the db.find lookup happens.

Common situations: Passing an unvalidated request parameter or form field straight into a lookup function; optional path/route params defaulting to empty string; refactoring a signature to accept id without validating at the boundary.

Related errors


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