affaan-m/ECC · error

not_found

not_found

Error message

not_found

What it means

REST example from the api-design skill: a resource-level handler for GET /api/v1/orders/:id calls Order.findById, and when the lookup returns null it responds 404 with { error: { code: 'not_found' } } before any ownership check runs. Reaching the 404 means the id simply does not match a row (the ownership 403 is a separate, later branch).

Source

Thrown at skills/api-design/SKILL.md:316

### Token-Based Auth

```
# Bearer token in Authorization header
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

# API key (for server-to-server)
GET /api/v1/data
X-API-Key: sk_live_abc123
```

### Authorization Patterns

```typescript
// Resource-level: check ownership
app.get("/api/v1/orders/:id", async (req, res) => {
  const order = await Order.findById(req.params.id);
  if (!order) return res.status(404).json({ error: { code: "not_found" } });
  if (order.userId !== req.user.id) return res.status(403).json({ error: { code: "forbidden" } });
  return res.json({ data: order });
});

// Role-based: check permissions
app.delete("/api/v1/users/:id", requireRole("admin"), async (req, res) => {
  await User.delete(req.params.id);
  return res.status(204).send();
});
```

## Rate Limiting

### Headers

```
HTTP/1.1 200 OK
X-RateLimit-Limit: 100

View on GitHub (pinned to d8409a4b08)

Solutions

  1. Verify the id exists by querying the store directly (or the source system that gave you the id)
  2. Check whether the record was deleted or the id came from a stale cache/another environment
  3. Confirm the id format matches what the API expects (UUID string vs numeric id) with no whitespace or case drift
  4. On the client, treat 404 with code 'not_found' as a terminal condition: clear the cached id / redirect, do not retry

Example fix

// before - client assumes the order exists and crashes on undefined
const order = await (await fetch(`/api/v1/orders/${id}`)).json()
render(order.items)

// after - branch on the 404 code
const res = await fetch(`/api/v1/orders/${id}`)
if (res.status === 404) return notFoundScreen()
const { data } = await res.json()
render(data.items)
Defensive patterns

Strategy: validation

Validate before calling

// Client: sanity-check the id format before spending a round trip
const isUuid = (id: string) =>
  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id.trim())
if (!isUuid(orderId)) throw new Error(`malformed order id: ${orderId}`)

Try / catch

const res = await fetch(`/api/v1/orders/${encodeURIComponent(orderId)}`)
switch (res.status) {
  case 200: return await res.json()
  case 404: return null            // terminal: caller decides (clear cache / show empty state), do not retry
  case 403: throw new ForbiddenError()
  default:   throw new Error(`unexpected status ${res.status}`)
}

Prevention

When it happens

Trigger: GET /api/v1/orders/:id with an id that was never created, was deleted, or has a typo/extra whitespace; an id in a different format than stored (UUID vs integer); a scoped/filtered findById whose filters exclude the row.

Common situations: Client caching an id from a previous environment (dev id sent to staging); the record was deleted by another user or a cleanup job; test database not seeded; copy-pasting ids with trailing newlines or mismatched case on case-sensitive stores.

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 affaan-m/ECC@d8409a4b08 (2026-08-26). Data as JSON: /api/errors/4500fc73124b22f0. Report an issue: GitHub.