Skip to content
Open
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
64 changes: 64 additions & 0 deletions src/components/learn-aggregator/assets/pen.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/components/learn-aggregator/learn-pages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ const _items: Record<
icon: new URL("./assets/solve.svg", import.meta.url).href,
section: "best-practices",
},
"error-handling": {
description:
"Compare top-level errors and errors-as-data, and learn when to use each approach for exceptional versus expected failures.",
icon: new URL("./assets/construction.svg", import.meta.url).href,
section: "best-practices",
},
"global-object-identification": {
description:
"Use globally unique IDs and the Node interface to enable caching, refetching, and efficient schema traversal.",
Expand Down Expand Up @@ -153,6 +159,12 @@ const _items: Record<
icon: new URL("./assets/construction.svg", import.meta.url).href,
section: "best-practices",
},
"naming-design": {
description:
"Learn how to establish naming conventions and design standards for your GraphQL schema.",
icon: new URL("./assets/pen.svg", import.meta.url).href,
section: "best-practices",
},
}

const learnPages = _items as Record<LearnPagePath, LearnPageItem | null>
Expand Down
6 changes: 6 additions & 0 deletions src/pages/learn/_meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,17 @@ export default {
authorization: "",
pagination: "",
"schema-design": "Schema Design",
"error-handling": "Error Handling",
"global-object-identification": "",
caching: "",
performance: "",
security: "",
federation: "",
"robust-applications": "Robust Applications",
"debug-errors": "Common GraphQL over HTTP Errors",
"-- 3": {
type: "separator",
title: "Schema Governance",
},
"naming-design": "Naming Conventions and Design Standards",
}
59 changes: 59 additions & 0 deletions src/pages/learn/error-handling.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Error Handling

GraphQL gives you two complementary ways to communicate errors to clients: the top-level `errors` array for exceptional failures, and errors-as-data for expected, domain-specific failures. Using the right approach for each situation keeps your API predictable and makes error states discoverable through the schema.

## Use top-level errors for exceptional failures

The standard GraphQL `errors` array handles infrastructure and system failures:

```json
{
"data": null,
"errors": [{
"message": "Database connection failed",
"extensions": {
"code": "INTERNAL_SERVER_ERROR"
}
}]
}
```

## Use errors-as-data for domain errors

Business logic errors belong in the schema as structured types:

```graphql
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
}

type CreateUserPayload {
user: User
userErrors: [UserError!]!
}

type UserError {
message: String!
field: [String!]
code: UserErrorCode!
}

enum UserErrorCode {
USERNAME_TAKEN
INVALID_EMAIL
PASSWORD_TOO_SHORT
}
```

This pattern makes errors discoverable through introspection and provides type safety.

## Choose based on whether errors are exceptional

| Error type | Pattern | Example |
|-----------|---------|---------|
| Infrastructure failure | Top-level error | Database timeout, network error |
| Invalid GraphQL | Top-level error | Syntax error, unknown field |
| Authentication required | Top-level error | Missing auth token |
| Business rule violation | errors-as-data | Username taken, invalid email |
| Validation failure | errors-as-data | Required field missing |
| Domain constraint | errors-as-data | Insufficient inventory |
Loading
Loading