Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .agents/skills/constructive-graphql/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ const newUser = await db.user.create({
}).execute().unwrap();
```

> **Error handling:** `.execute()` returns a discriminated union — it does NOT throw.
> Chain `.execute().unwrap()` to get throw-on-error behavior. See [codegen-error-handling.md](./references/codegen-error-handling.md) for full patterns.

## Quick Start: Search

The simplest way to search — `fullTextSearch` fans a single string to all text-compatible algorithms automatically:
Expand Down Expand Up @@ -167,7 +170,7 @@ See [search.md](./references/search.md) for the decision matrix and combined que
| [codegen-orm-output.md](./references/codegen-orm-output.md) | ORM generated output structure | Understanding what codegen produces |
| [codegen-hooks-patterns.md](./references/codegen-hooks-patterns.md) | React Query hook patterns | Using generated hooks in React components |
| [codegen-hooks-output.md](./references/codegen-hooks-output.md) | Hooks generated output structure | Understanding hook file structure |
| [codegen-error-handling.md](./references/codegen-error-handling.md) | Error handling patterns | `.unwrap()`, `.unwrapOr()`, discriminated unions |
| [codegen-error-handling.md](./references/codegen-error-handling.md) | **Error handling patterns (read first!)** | `.unwrap()` vs `.execute()`, silent error trap, `QueryResult<T>` discriminated union |
| [codegen-relations.md](./references/codegen-relations.md) | Relation queries and M:N mutations | Nested selects, belongsTo, hasMany, manyToMany, composite PKs, `expose_in_api`, add/remove methods |
| [codegen-query-keys.md](./references/codegen-query-keys.md) | Query key factory | Cache invalidation, `invalidate.*`, `remove.*` |
| [codegen-node-http-adapter.md](./references/codegen-node-http-adapter.md) | Node.js HTTP adapter | Subdomain routing in Node.js |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@

Comprehensive guide to handling errors with generated code.

## CRITICAL: `execute()` Does NOT Throw

**The most common mistake** when using the Constructive ORM is wrapping `.execute()` in a bare `try/catch` and assuming errors will be caught. **They will not.**

`.execute()` returns a **discriminated union** — it **never throws an exception** on GraphQL or HTTP errors. Instead, it returns `{ ok: false, ... }`. A `try/catch` around `.execute()` will silently swallow errors because no exception is raised.

```typescript
// BUG: Silent error swallowing — errors are NEVER caught here
try {
const result = await db.user.findMany({ select: { id: true } }).execute();
// result may be { ok: false, error: {...} }
// but no exception is thrown, so the catch block is skipped entirely
const users = result.value; // users is undefined — silent failure!
} catch (error) {
// This NEVER runs for GraphQL/HTTP errors
console.error(error);
}
```

**The fix:** Use `.execute().unwrap()` to get throw-on-error behavior, or check `.ok` explicitly:

```typescript
// Option A — .execute().unwrap() throws on error (recommended):
const users = await db.user.findMany({ select: { id: true } }).execute().unwrap();

// Option B — check .ok for control flow:
const result = await db.user.findMany({ select: { id: true } }).execute();
if (!result.ok) {
console.error(result.error.message);
return [];
}
return result.value;
```

## Discriminated Unions

The ORM returns discriminated union results for type-safe error handling:
Expand Down