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.

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.

Appendix: 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)