Skip to content

Commit b4b8482

Browse files
authored
[D1] Improving D1 error doc page. (#22948)
* Improving D1 error doc page. * Separating out the two tables * m * Updating recommendation (Feedback part 1) * Adding warning about retry operation * Update to wording * Removing unnecessary line * Explicitly directing attention for errors where retry could be unsafe
1 parent 67082a2 commit b4b8482

File tree

1 file changed

+43
-38
lines changed

1 file changed

+43
-38
lines changed

src/content/docs/d1/observability/debug-d1.mdx

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,72 +6,77 @@ sidebar:
66

77
---
88

9-
D1 allows you to capture exceptions and log errors returned when querying a database. To debug D1, you will use the same tools available when [debugging Workers](/workers/observability/).
9+
import { Example } from "~/components";
1010

11-
## Handle errors
11+
D1 allows you to capture exceptions and log errors returned when querying a database. To debug D1, you will use the same tools available when [debugging Workers](/workers/observability/).
1212

13-
The D1 [Workers Binding API](/d1/worker-api/) returns detailed error messages within an `Error` object.
13+
D1's [`stmt.`](/d1/worker-api/prepared-statements/) and [`db.`](/d1/worker-api/d1-database/) methods throw an [Error object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) whenever an error occurs. To capture exceptions, log the `e.message` value.
1414

15-
To ensure you are capturing the full error message, log or return `e.message` as follows:
15+
For example, the code below has a query with an invalid keyword - `INSERTZ` instead of `INSERT`:
1616

17-
```ts
17+
```js
1818
try {
19+
// This is an intentional misspelling
1920
await db.exec("INSERTZ INTO my_table (name, employees) VALUES ()");
2021
} catch (e: any) {
2122
console.error({
2223
message: e.message
2324
});
2425
}
25-
/*
26-
{
27-
"message": "D1_EXEC_ERROR: Error in line 1: INSERTZ INTO my_table (name, employees) VALUES (): sql error: near \"INSERTZ\": syntax error in INSERTZ INTO my_table (name, employees) VALUES () at offset 0"
28-
}
29-
*/
3026
```
3127

32-
### Errors
28+
The code above throws the following error message:
3329

34-
The [`stmt.`](/d1/worker-api/prepared-statements/) and [`db.`](/d1/worker-api/d1-database/) methods throw an [Error object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) whenever an error occurs.
30+
```json
31+
{
32+
"message": "D1_EXEC_ERROR: Error in line 1: INSERTZ INTO my_table (name, employees) VALUES (): sql error: near \"INSERTZ\": syntax error in INSERTZ INTO my_table (name, employees) VALUES () at offset 0"
33+
}
34+
```
3535

3636
:::note
3737
Prior to [`wrangler` 3.1.1](https://github.com/cloudflare/workers-sdk/releases/tag/wrangler%403.1.1), D1 JavaScript errors used the [cause property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) for detailed error messages.
3838

3939
To inspect these errors when using older versions of `wrangler`, you should log `error?.cause?.message`.
4040
:::
4141

42-
To capture exceptions, log the `Error.message` value. For example, the code below has a query with an invalid keyword - `INSERTZ` instead of `INSERT`:
42+
## Error list
4343

44-
```js
45-
try {
46-
// This is an intentional misspelling
47-
await db.exec("INSERTZ INTO my_table (name, employees) VALUES ()");
48-
} catch (e: any) {
49-
console.error({
50-
message: e.message
51-
});
52-
}
53-
```
44+
D1 returns the following error constants, in addition to the extended (detailed) error message:
5445

55-
The code above throws the following error message:
46+
| Error message | Description | Recommended action |
47+
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
48+
| `D1_ERROR` | Prefix of a specific D1 error. | Refer to "List of D1_ERRORs" below for more detail about your specific error. |
49+
| `D1_EXEC_ERROR` | Exec error in line x: y error. | |
50+
| `D1_TYPE_ERROR` | Returned when there is a mismatch in the type between a column and a value. A common cause is supplying an `undefined` variable (unsupported) instead of `null`. | Ensure the type of the value and the column match. |
51+
| `D1_COLUMN_NOTFOUND` | Column not found. | Ensure you have selected a column which exists in the database. |
5652

57-
```json
58-
{
59-
"message": "D1_EXEC_ERROR: Error in line 1: INSERTZ INTO my_table (name, employees) VALUES (): sql error: near \"INSERTZ\": syntax error in INSERTZ INTO my_table (name, employees) VALUES () at offset 0"
60-
}
61-
```
53+
The following table lists specific instances of `D1_ERROR`.
6254

63-
### Error list
55+
<Example title="List of D1_ERRORs">
6456

65-
D1 returns the following error constants, in addition to the extended (detailed) error message:
57+
:::note[Retry operations]
58+
While some D1 errors can be resolved by retrying the operation, retrying is only safe if your query is idempotent (produces the same result when executed multiple times).
6659

67-
| Message | Cause |
68-
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
69-
| `D1_ERROR` | Generic error. |
70-
| `D1_TYPE_ERROR` | Returned when there is a mismatch in the type between a column and a value. A common cause is supplying an `undefined` variable (unsupported) instead of `null`. |
71-
| `D1_COLUMN_NOTFOUND` | Column not found. |
72-
| `D1_DUMP_ERROR` | Database dump error. |
73-
| `D1_EXEC_ERROR` | Exec error in line x: y error. |
60+
Before retrying any failed operation:
61+
- Verify your query is idempotent (for example, read-only operations, or queries such as `CREATE TABLE IF NOT EXISTS`).
62+
- Consider implementing application-level checks to identify if the operation can be retried, and retrying only when it is safe and necessary.
63+
:::
7464

65+
| `D1_ERROR` type | Description | Recommended action |
66+
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
67+
| `D1 DB reset because its code was updated.` | Cloudflare has updated the code for D1 (or the underlying Durable Object), and the Durable Object which contains the D1 database is restarting. | Retry the operation. |
68+
| `Internal error while starting up D1 DB storage caused object to be reset.` | The Durable Object containing the D1 database is failing to start. | Retry the operation. |
69+
| `Network connection lost.` | A network error. | Retry the operation. Refer to the "Retry operation" note above. |
70+
| `Internal error in D1 DB storage caused object to be reset.` | An error has caused the D1 database to restart. | Retry the operation. |
71+
| `Cannot resolve D1 DB due to transient issue on remote node.` | The query cannot reach the Durable Object containing the D1 database. | Retry the operation. Refer to the "Retry operation" note above. |
72+
| `Can't read from request stream because client disconnected.` | A query request was made (e.g. uploading a SQL query), but the connection was closed during the query was fully executed. | App action: Retry the operation, and ensure the connection stays open. |
73+
| `D1 DB storage operation exceeded timeout which caused object to be reset.` | A query is trying to write a large amount of information (e.g. GBs), and is taking too long. | App action: Optimize the queries (so that each query takes less time), send fewer requests by spreading the load over time, or shard the queries. |
74+
| `D1 DB is overloaded. Requests queued for too long.` | The requests to the D1 database are queued for too long, either because there are too many requests, or the queued requests are taking too long. | App action: Optimize the queries (so that each query takes less time), send fewer requests by spreading the load over time, or shard the queries. |
75+
| `D1 DB is overloaded. Too many requests queued.` | The request queue to the D1 database is too long, either because there are too many requests, or the queued requests are taking too long. | App action: Optimize the queries (so that each query takes less time), send fewer requests by spreading the load over time, or shard the queries. |
76+
| `D1 DB's isolate exceeded its memory limit and was reset.` | A query loaded too much into memory, causing the D1 database to crash. | App action: Optimize the queries (so that each query takes less time), send fewer requests by spreading the load over time, or shard the queries. |
77+
| `D1 DB exceeded its CPU time limit and was reset.` | A query is taking up a lot of CPU time (e.g. scanning over 9 GB table, or attempting a large import/export). | App action: Split the query into smaller shards. |
78+
79+
</Example>
7580

7681
## View logs
7782

0 commit comments

Comments
 (0)