sickn33/agentic-awesome-skills · warning · Error

ID required

Error message

ID required

What it means

The first throw in fp-ts-errors' motivating example: getUser is called with a falsy id (empty string, null, undefined) before any DB lookup happens. The skill uses it to show that the signature getUser(id: string): User hides two distinct failure modes from callers.

Source

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

- When accumulating multiple validation errors

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

View on GitHub (pinned to 58d857988f)

Solutions

  1. Validate ids at the boundary (non-empty string check) before calling services
  2. Make the signature honest: return Either<DomainError, User> as the skill teaches
  3. Use a NonEmptyString branded type for ids so empty ids fail to compile

Example fix

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

// after
const getUser = (id: string): E.Either<DomainError, User> =>
  id.trim() === ''
    ? E.left({ _tag: 'InvalidId' })
    : E.right(db.find(id) as User)
Defensive patterns

Strategy: validation

Validate before calling

const isValidId = (id: unknown): id is string =>
  typeof id === 'string' && id.trim().length > 0

Type guard

const isNonEmptyString = (s: unknown): s is string =>
  typeof s === 'string' && s.length > 0

Prevention

When it happens

Trigger: Calling getUser(''), getUser(null as any), or a value from an unvalidated route param where the id never got populated.

Common situations: Optional route/query params reaching services unchecked; destructured config fields that are undefined; test helpers calling with empty fixtures.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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