From da3e1a5d8c023b2fd6983222e42eeb324dc598d6 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 10:02:02 +0200 Subject: [PATCH 1/5] docs(errors): the two error references say which commands they cover and link each other The generator writes a scope sentence on each page, a namespace list built from the source's sections, and a note on the CLI namespace that both pages have. Neither page claims to list every code any more. Both pages are regenerated from main. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../docs/content/docs/cli/error-reference.mdx | 42 +++---- .../docs/orm/reference/error-reference.mdx | 45 ++++---- .../docs/scripts/generate-error-reference.mjs | 106 +++++++++++++++--- scripts/generate-error-reference.test.ts | 71 ++++++++++++ 4 files changed, 208 insertions(+), 56 deletions(-) diff --git a/apps/docs/content/docs/cli/error-reference.mdx b/apps/docs/content/docs/cli/error-reference.mdx index bc2a7d05c79..dbc5c43c9e2 100644 --- a/apps/docs/content/docs/cli/error-reference.mdx +++ b/apps/docs/content/docs/cli/error-reference.mdx @@ -1,38 +1,38 @@ --- title: Error reference -description: Every structured error code the unified Prisma CLI can emit, by namespace, with the condition that raises it. +description: The structured error codes of the Prisma CLI platform commands, by namespace, with the condition that raises each one. url: /cli/error-reference metaTitle: Error reference | Prisma CLI -metaDescription: Every structured error code the unified Prisma CLI can emit, by namespace, with the condition that raises it. +metaDescription: The structured error codes of the Prisma CLI platform commands, by namespace, with the condition that raises each one. --- {/* Generated by scripts/generate-error-reference.mjs from https://github.com/prisma/prisma-cli/blob/main/docs/reference/error-reference.md - Do not edit by hand — changes are overwritten by the sync workflow. */} + Do not edit by hand. The sync workflow overwrites changes. */} -Every user-facing error the unified Prisma CLI emits is a structured envelope identified by a dotted `NAMESPACE.SUBCODE` code (see [Error Conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md) and [ADR 0003](https://github.com/prisma/prisma-cli/blob/main/docs/architecture/adrs/0003-structured-output-and-errors.md)). This page lists every published code. Each code anchors as `#` — the fragment an emitted error's `docsUrl` resolves to. This page is generated from the canonical registry in the `prisma/prisma-cli` repository, whose CI requires every code in production source to be documented before it ships. +Every user-facing error the unified Prisma CLI emits is a structured envelope identified by a dotted `NAMESPACE.SUBCODE` code (see [Error Conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md) and [ADR 0003](https://github.com/prisma/prisma-cli/blob/main/docs/architecture/adrs/0003-structured-output-and-errors.md)). This page lists the codes from every `prisma` command except the Prisma ORM ones. The codes from `prisma contract`, `prisma db`, `prisma migration`, and `prisma orm`, and the codes your app can raise at runtime, are on the [Prisma ORM error reference](/orm/reference/error-reference). When an error prints a `docsUrl`, that link opens the code's entry on this page. This page is generated from the `prisma/prisma-cli` repository. Recognize an error programmatically by running with `--json` and matching on `error.code` in the emitted envelope — never on message text. Envelopes carry `message`, and optionally `why`, `fix`, `where`, `meta`, `cause`, `nextActions`, and `docsUrl`. Most codes on this page are expected failures. Some are warn-severity diagnostics that ride a successful run: the command completes and exits `0`, and the diagnostic carries the code (the entry says so where it applies). The process exit-code contract is in [Error Conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md). -Every code on this page is assigned where the error is raised, and this page lists every code the CLI can emit. No boundary invents a code from a server response or rewrites one on the way out, so an error's code never depends on which command you reached the failure through. When a REST API request fails, the CLI raises the domain's registered `*.API_ERROR` code and carries the API's own code and HTTP status in `meta.apiCode` and `meta.status`, where they are data you can read rather than a code you have to guess at. - -Namespaces: - -| Namespace | Covers | -| --- | --- | -| `AUTH` | Workspace authentication and sessions (`prisma auth`, credential resolution) | -| `BRANCH` | Branch listing (`prisma branch`) | -| `BUCKET` | Bucket and bucket-key management (`prisma bucket`) | -| `CLI` | Engine-level invocation: arguments, config loading, prompts, consent, credentials, child processes | -| `FEEDBACK` | Sending product feedback (`prisma feedback`) | -| `GIT` | Git repository connections (`prisma git`) | -| `INIT` | Project initialization diagnostics (`prisma init`) | -| `POSTGRES` | Database management (`prisma postgres`) | -| `PROJECT` | Project and environment management (`prisma project`) | -| `SERVICE` | Deployed service management (`prisma service`) | -| `SKILLS` | Agent-skill delivery (`prisma skills`) | +Every code on this page is assigned where the error is raised. No boundary invents a code from a server response or rewrites one on the way out, so an error's code never depends on which command you reached the failure through. When a REST API request fails, the CLI raises the domain's registered `*.API_ERROR` code and carries the API's own code and HTTP status in `meta.apiCode` and `meta.status`, where they are data you can read rather than a code you have to guess at. + +Namespaces on this page: + +- [`AUTH`](#auth): Workspace authentication and sessions (`prisma auth`, credential resolution) +- [`BRANCH`](#branch): Branch listing (`prisma branch`) +- [`BUCKET`](#bucket): Bucket and bucket-key management (`prisma bucket`) +- [`CLI`](#cli): Engine-level invocation: arguments, config loading, prompts, consent, credentials, child processes +- [`FEEDBACK`](#feedback): Sending product feedback (`prisma feedback`) +- [`GIT`](#git): Git repository connections (`prisma git`) +- [`INIT`](#init): Project initialization diagnostics (`prisma init`) +- [`POSTGRES`](#postgres): Database management (`prisma postgres`) +- [`PROJECT`](#project): Project and environment management (`prisma project`) +- [`SERVICE`](#service): Deployed service management (`prisma service`) +- [`SKILLS`](#skills): Agent-skill delivery (`prisma skills`) + +This page and the [Prisma ORM error reference](/orm/reference/error-reference) both have a `CLI` namespace, with different codes in each. A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on the other page. One from any other `prisma` command is on this page. ## AUTH diff --git a/apps/docs/content/docs/orm/reference/error-reference.mdx b/apps/docs/content/docs/orm/reference/error-reference.mdx index 70609cd2e86..a72dee33c4a 100644 --- a/apps/docs/content/docs/orm/reference/error-reference.mdx +++ b/apps/docs/content/docs/orm/reference/error-reference.mdx @@ -1,16 +1,16 @@ --- title: Error reference -description: Every structured error code Prisma ORM can emit, by namespace, with the condition that raises it. +description: The structured error codes of the Prisma ORM commands, runtime, and extensions, by namespace, with the condition that raises each one. url: /orm/reference/error-reference metaTitle: Prisma ORM error reference -metaDescription: Every structured error code Prisma ORM can emit, by namespace, with the condition that raises it. +metaDescription: The structured error codes of the Prisma ORM commands, runtime, and extensions, by namespace, with the condition that raises each one. --- {/* Generated by scripts/generate-error-reference.mjs from https://github.com/prisma/prisma/blob/main/docs/reference/error-reference.md - Do not edit by hand — changes are overwritten by the sync workflow. */} + Do not edit by hand. The sync workflow overwrites changes. */} -Every user-facing Prisma ORM error is a structured envelope identified by a dotted `NAMESPACE.SUBCODE` code (see [ADR 239](https://github.com/prisma/prisma/blob/main/docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md) and [Error Handling](https://github.com/prisma/prisma/blob/main/docs/Error%20Handling.md)). This page lists every published code. Each code anchors as `#` — the exact fragment every emitted error carries in its `docsUrl`. This page is generated from the canonical reference in the `prisma/prisma` repository, whose CI requires every code in production source to be documented before it ships. +Every user-facing Prisma ORM error is a structured envelope identified by a dotted `NAMESPACE.SUBCODE` code (see [ADR 239](https://github.com/prisma/prisma/blob/main/docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md) and [Error Handling](https://github.com/prisma/prisma/blob/main/docs/Error%20Handling.md)). This page lists the codes from the Prisma ORM commands, which start with `prisma contract`, `prisma db`, `prisma migration`, and `prisma orm`, and the codes your app can raise at runtime, including from extensions. Every other `prisma` command has its codes on the [CLI error reference](/cli/error-reference). When an error prints a `docsUrl`, that link opens the code's entry on this page. This page is generated from the `prisma/prisma` repository. Recognize an error programmatically with `isStructuredError` from your facade package's `utils/structured-error` subpath (for example `@prisma/orm-postgres/utils/structured-error`) and match on `error.code`, never `instanceof`. Envelopes carry `message`, and optionally `why`, `fix`, `where`, `cause`, `docsUrl`, and the structured context each entry below lists as its **Payload**. The payload arrives on `error.meta` when the envelope was built by `structuredError` and on `error.details` when it was built by `runtimeError`; a few codes are raised both ways, so read whichever property the envelope carries. @@ -22,24 +22,25 @@ A command may also **complete with findings**: it ran to its end and has a resul Codes that predate the dotted scheme were renamed at 0.16; the full old→new crosswalk (`PN-DOMAIN-NNNN` → `NAMESPACE.SUBCODE`) is in [ADR 239](https://github.com/prisma/prisma/blob/main/docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md). -Namespaces: - -| Namespace | Covers | -| --- | --- | -| `CONFIG` | Loading and validating `prisma.config.ts` | -| `CLI` | Command-line argument and invocation errors | -| `CONTRACT` | Contract authoring, emission, validation, and the contract↔database relationship (markers, schema verification) | -| `PSL` | The PSL source text itself (parse, format, interpret), including a Prisma ORM 7 schema read as the contract source | -| `ORM` | ORM client and query-builder DSL API misuse | -| `RUNTIME` | Query execution and runtime wiring | -| `DRIVER` | Database driver connection and protocol failures | -| `MIGRATION` | Migration authoring, planning, checking, and execution | -| `PLAN` | Query plan constraints | -| `BUDGET` | Query budget violations | -| `LINT` | Query lint findings | -| `PARADEDB` | ParadeDB extension: search-function arguments | -| `POSTGIS` | PostGIS extension: geometry construction and validation | -| `SUPABASE` | Supabase extension: config wiring and JWT handling | +Namespaces on this page: + +- [`CONFIG`](#config): Loading and validating `prisma.config.ts` +- [`CLI`](#cli): Command-line argument and invocation errors +- [`CONTRACT`](#contract): Contract authoring, emission, validation, and the contract↔database relationship (markers, schema verification) +- [`PSL`](#psl): The PSL source text itself (parse, format, interpret), including a Prisma ORM 7 schema read as the contract source +- [`ORM`](#orm): ORM client and query-builder DSL API misuse +- [`RUNTIME`](#runtime): Query execution and runtime wiring +- [`DRIVER`](#driver): Database driver connection and protocol failures +- [`MIGRATION`](#migration): Migration authoring, planning, checking, and execution +- [`PLAN`](#plan): Query plan constraints +- [`BUDGET`](#budget): Query budget violations +- [`LINT`](#lint): Query lint findings +- [`PARADEDB`](#paradedb): ParadeDB extension: search-function arguments +- [`POSTGIS`](#postgis): PostGIS extension: geometry construction and validation +- [`SUPABASE`](#supabase): Supabase extension: config wiring and JWT handling +- [`TESTKIT`](#testkit) + +This page and the [CLI error reference](/cli/error-reference) both have a `CLI` namespace, with different codes in each. A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on this page. One from any other `prisma` command is on the other page. ## CONFIG diff --git a/apps/docs/scripts/generate-error-reference.mjs b/apps/docs/scripts/generate-error-reference.mjs index ab35da41614..4666398ef3b 100644 --- a/apps/docs/scripts/generate-error-reference.mjs +++ b/apps/docs/scripts/generate-error-reference.mjs @@ -89,21 +89,31 @@ function applyCliNamingStandard(body) { return replaceInProse(applyVersionNamingStandard(body), /\bManagement API\b/g, "REST API"); } +const ORM_PAGE = "[Prisma ORM error reference](/orm/reference/error-reference)"; +const CLI_PAGE = "[CLI error reference](/cli/error-reference)"; + export const TARGETS = { orm: { sourceRepo: "prisma/prisma", output: join(HERE, "../content/docs/orm/reference/error-reference.mdx"), applyNamingStandard: applyOrmNamingStandard, hostedIntro: - "Each code anchors as `#` — the exact fragment every emitted error carries in its " + - "`docsUrl`. This page is generated from the canonical reference in the `prisma/prisma` " + - "repository, whose CI requires every code in production source to be documented before it ships.", + "When an error prints a `docsUrl`, that link opens the code's entry on this page. " + + "This page is generated from the `prisma/prisma` repository.", + scope: + "This page lists the codes from the Prisma ORM commands, which start with `prisma contract`, " + + "`prisma db`, `prisma migration`, and `prisma orm`, and the codes your app can raise at runtime, " + + `including from extensions. Every other \`prisma\` command has its codes on the ${CLI_PAGE}.`, + sharedCliNamespace: + `This page and the ${CLI_PAGE} both have a \`CLI\` namespace, with different codes in each. ` + + "A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on this " + + "page. One from any other `prisma` command is on the other page.", frontmatter: `--- title: Error reference -description: Every structured error code Prisma ORM can emit, by namespace, with the condition that raises it. +description: The structured error codes of the Prisma ORM commands, runtime, and extensions, by namespace, with the condition that raises each one. url: /orm/reference/error-reference metaTitle: Prisma ORM error reference -metaDescription: Every structured error code Prisma ORM can emit, by namespace, with the condition that raises it. +metaDescription: The structured error codes of the Prisma ORM commands, runtime, and extensions, by namespace, with the condition that raises each one. --- `, }, @@ -112,15 +122,22 @@ metaDescription: Every structured error code Prisma ORM can emit, by namespace, output: join(HERE, "../content/docs/cli/error-reference.mdx"), applyNamingStandard: applyCliNamingStandard, hostedIntro: - "Each code anchors as `#` — the fragment an emitted error's `docsUrl` resolves to. " + - "This page is generated from the canonical registry in the `prisma/prisma-cli` repository, " + - "whose CI requires every code in production source to be documented before it ships.", + "When an error prints a `docsUrl`, that link opens the code's entry on this page. " + + "This page is generated from the `prisma/prisma-cli` repository.", + scope: + "This page lists the codes from every `prisma` command except the Prisma ORM ones. The codes " + + "from `prisma contract`, `prisma db`, `prisma migration`, and `prisma orm`, and the codes your " + + `app can raise at runtime, are on the ${ORM_PAGE}.`, + sharedCliNamespace: + `This page and the ${ORM_PAGE} both have a \`CLI\` namespace, with different codes in each. ` + + "A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on the " + + "other page. One from any other `prisma` command is on this page.", frontmatter: `--- title: Error reference -description: Every structured error code the unified Prisma CLI can emit, by namespace, with the condition that raises it. +description: The structured error codes of the Prisma CLI platform commands, by namespace, with the condition that raises each one. url: /cli/error-reference metaTitle: Error reference | Prisma CLI -metaDescription: Every structured error code the unified Prisma CLI can emit, by namespace, with the condition that raises it. +metaDescription: The structured error codes of the Prisma CLI platform commands, by namespace, with the condition that raises each one. --- `, }, @@ -159,6 +176,64 @@ function assertMdxSafe(markdown) { } } +const SOURCE_SCOPE_SENTENCE = "This page lists every published code."; + +// Each page covers a subset of the CLI's commands, so the source's claims to +// list every code are replaced with the target's scope and a link to the +// other page. +function addScope(body, target, warnings) { + body = body.replace(", and this page lists every code the CLI can emit.", "."); + if (body.includes(SOURCE_SCOPE_SENTENCE)) { + return body.replace(SOURCE_SCOPE_SENTENCE, target.scope); + } + warnings.push( + `The source no longer contains ${JSON.stringify(SOURCE_SCOPE_SENTENCE)}. ` + + "The scope sentence was inserted after the first paragraph instead.", + ); + const firstParagraphEnd = body.search(/\n\s*\n/); + if (firstParagraphEnd === -1) return `${body.trimEnd()}\n\n${target.scope}\n`; + return `${body.slice(0, firstParagraphEnd)}\n\n${target.scope}${body.slice(firstParagraphEnd)}`; +} + +/** Fumadocs' heading slug (github-slugger) for the heading shapes the sources use. */ +function headingSlug(text) { + return text + .toLowerCase() + .replace(/[^\p{L}\p{N}\s_-]/gu, "") + .replace(/\s/g, "-"); +} + +const SOURCE_NAMESPACE_TABLE = /^Namespaces:\n\n((?:\|.*\|\n)+)\n?/m; + +// The source's own namespace table can fall behind its `##` sections, so the +// list is rebuilt from the sections. The table still supplies each +// namespace's description. +function replaceNamespaceList(body, target) { + const descriptions = new Map(); + const table = body.match(SOURCE_NAMESPACE_TABLE); + if (table) { + body = body.replace(SOURCE_NAMESPACE_TABLE, ""); + for (const row of table[1].split("\n")) { + const cells = row.split("|").map((cell) => cell.trim()); + const namespace = cells[1]?.match(/^`([^`]+)`$/)?.[1]; + if (namespace && cells[2]) descriptions.set(namespace, cells[2]); + } + } + + const namespaces = [...body.matchAll(/^## (.+)$/gm)].map((match) => match[1].trim()); + if (namespaces.length === 0) return body; + const items = namespaces.map((namespace) => { + const description = descriptions.get(namespace); + const link = `[\`${namespace}\`](#${headingSlug(namespace)})`; + return description ? `- ${link}: ${description}` : `- ${link}`; + }); + const list = ["Namespaces on this page:", "", ...items, ""]; + if (namespaces.includes("CLI")) list.push(target.sharedCliNamespace, ""); + + const firstSection = body.search(/^## /m); + return `${body.slice(0, firstSection)}${list.join("\n")}\n${body.slice(firstSection)}`; +} + export function transform(target, markdown) { assertMdxSafe(markdown); @@ -173,6 +248,10 @@ export function transform(target, markdown) { target.hostedIntro, ); + const warnings = []; + body = addScope(body, target, warnings); + body = replaceNamespaceList(body, target); + // Repo-relative links point at files that only exist in the source repo. const blobBase = `https://github.com/${target.sourceRepo}/blob/main/docs/reference/`; body = body.replace(/\]\((\.\.?\/[^)]+)\)/g, (_, linkTarget) => { @@ -207,11 +286,11 @@ export function transform(target, markdown) { const header = `${target.frontmatter} {/* Generated by scripts/generate-error-reference.mjs from https://github.com/${target.sourceRepo}/blob/main/docs/reference/error-reference.md - Do not edit by hand — changes are overwritten by the sync workflow. */} + Do not edit by hand. The sync workflow overwrites changes. */} `; - return { mdx: header + body, codeCount: codes.length }; + return { mdx: header + body, codeCount: codes.length, warnings }; } if (process.argv[1] === fileURLToPath(import.meta.url)) { @@ -222,7 +301,8 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { `Unknown --target ${JSON.stringify(targetName)}. Known: ${Object.keys(TARGETS).join(", ")}`, ); } - const { mdx, codeCount } = transform(target, await loadSource(target)); + const { mdx, codeCount, warnings } = transform(target, await loadSource(target)); + for (const warning of warnings) console.warn(`Warning: ${warning}`); writeFileSync(target.output, mdx); console.log(`Wrote ${target.output} with ${codeCount} error codes.`); } diff --git a/scripts/generate-error-reference.test.ts b/scripts/generate-error-reference.test.ts index d90a13c45f6..05954efa18e 100644 --- a/scripts/generate-error-reference.test.ts +++ b/scripts/generate-error-reference.test.ts @@ -87,3 +87,74 @@ test("a duplicate undotted code is rejected", () => { /Duplicate error codes in source: PSL_PRESET_CONFLICT/, ); }); + +const intro = "Every error is a structured envelope. This page lists every published code."; + +function sourceWith({ intro: firstParagraph = intro, namespaces = ["AUTH", "CLI"] }: { intro?: string; namespaces?: string[] } = {}) { + const sections = namespaces.map( + (namespace) => `## ${namespace}\n\n### ${namespace}.FAILED\n\nIt failed.\n`, + ); + return [ + "# Error reference", + "", + firstParagraph, + "", + "Match on `error.code`.", + "", + "Namespaces:", + "", + "| Namespace | Covers |", + "| --- | --- |", + "| `AUTH` | Workspace authentication |", + "", + ...sections, + ].join("\n"); +} + +test("the source's claim to list every code becomes the target's scope with a link to the other page", () => { + const { mdx, warnings } = transform(TARGETS.orm, sourceWith()); + + assert.ok(mdx.includes(`Every error is a structured envelope. ${TARGETS.orm.scope}`)); + assert.ok(mdx.includes("[CLI error reference](/cli/error-reference)")); + assert.ok(!mdx.includes("This page lists every published code.")); + assert.deepEqual(warnings, []); +}); + +test("the namespace list comes from the source's sections and keeps the table's descriptions", () => { + const { mdx } = transform(TARGETS.cli, sourceWith({ namespaces: ["AUTH", "PROJECT"] })); + + assert.ok( + mdx.includes( + "Namespaces on this page:\n\n- [`AUTH`](#auth): Workspace authentication\n- [`PROJECT`](#project)\n", + ), + ); + assert.ok(!mdx.includes("| Namespace | Covers |")); + assert.ok(mdx.indexOf("Namespaces on this page:") < mdx.indexOf("## AUTH")); +}); + +test("the shared CLI namespace is explained only when the source has a CLI section", () => { + const withCli = transform(TARGETS.cli, sourceWith({ namespaces: ["AUTH", "CLI"] })).mdx; + const withoutCli = transform(TARGETS.cli, sourceWith({ namespaces: ["AUTH"] })).mdx; + + assert.ok(withCli.includes(TARGETS.cli.sharedCliNamespace)); + assert.ok(!withoutCli.includes("both have a `CLI` namespace")); +}); + +test("a reworded source intro still gets the scope sentence after its first paragraph, with a warning", () => { + const { mdx, warnings } = transform( + TARGETS.orm, + sourceWith({ intro: "Every error is a structured envelope." }), + ); + + assert.ok( + mdx.includes(`Every error is a structured envelope.\n\n${TARGETS.orm.scope}\n\nMatch on`), + ); + assert.equal(warnings.length, 1); + assert.match(warnings[0], /This page lists every published code/); +}); + +test("the frontmatter descriptions do not claim to list every code", () => { + for (const target of Object.values(TARGETS)) { + assert.doesNotMatch(target.frontmatter, /\bevery\b/i); + } +}); From 768a180d4b0bb02abe32c65a2f51d0e528be49b0 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 10:03:30 +0200 Subject: [PATCH 2/5] chore: retrigger the Vercel blog deployment Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden From 10c7c7451e3a272f7b6da145c5d3bb1a4f60a2f4 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 17:30:45 +0200 Subject: [PATCH 3/5] docs(errors): the CLI namespace note distinguishes engine codes from ORM command codes The command-line engine raises its own CLI.* codes for every prisma command, including the Prisma ORM ones, so a command-prefix rule sent readers to the wrong page for codes such as CLI.CONFIG_SECTION_INVALID from prisma contract emit. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- apps/docs/content/docs/cli/error-reference.mdx | 2 +- .../content/docs/orm/reference/error-reference.mdx | 2 +- apps/docs/scripts/generate-error-reference.mjs | 14 ++++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/docs/content/docs/cli/error-reference.mdx b/apps/docs/content/docs/cli/error-reference.mdx index dbc5c43c9e2..15afec12673 100644 --- a/apps/docs/content/docs/cli/error-reference.mdx +++ b/apps/docs/content/docs/cli/error-reference.mdx @@ -32,7 +32,7 @@ Namespaces on this page: - [`SERVICE`](#service): Deployed service management (`prisma service`) - [`SKILLS`](#skills): Agent-skill delivery (`prisma skills`) -This page and the [Prisma ORM error reference](/orm/reference/error-reference) both have a `CLI` namespace, with different codes in each. A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on the other page. One from any other `prisma` command is on this page. +This page and the [Prisma ORM error reference](/orm/reference/error-reference) both have a `CLI` namespace, with different codes in each. The `CLI.*` codes on this page come from the engine that runs every `prisma` command, for arguments, config loading, prompts, and consent, whatever the command was, for example `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. The Prisma ORM commands also raise `CLI.*` codes of their own, and those are on the Prisma ORM error reference. If a `CLI.*` code is not on this page, look on the other. ## AUTH diff --git a/apps/docs/content/docs/orm/reference/error-reference.mdx b/apps/docs/content/docs/orm/reference/error-reference.mdx index 0c63e2fe2ba..169515244f5 100644 --- a/apps/docs/content/docs/orm/reference/error-reference.mdx +++ b/apps/docs/content/docs/orm/reference/error-reference.mdx @@ -40,7 +40,7 @@ Namespaces on this page: - [`SUPABASE`](#supabase): Supabase extension: config wiring and JWT handling - [`TESTKIT`](#testkit) -This page and the [CLI error reference](/cli/error-reference) both have a `CLI` namespace, with different codes in each. A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on this page. One from any other `prisma` command is on the other page. +This page and the [CLI error reference](/cli/error-reference) both have a `CLI` namespace, with different codes in each. The engine that runs every `prisma` command raises its own `CLI.*` codes for arguments, config loading, prompts, and consent, and those are on the CLI error reference even when the command was a Prisma ORM one, for example `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. The `CLI.*` codes on this page are the ones the Prisma ORM commands raise themselves. If a `CLI.*` code is not on this page, look on the other. ## CONFIG diff --git a/apps/docs/scripts/generate-error-reference.mjs b/apps/docs/scripts/generate-error-reference.mjs index f9234f901c9..9afefeba281 100644 --- a/apps/docs/scripts/generate-error-reference.mjs +++ b/apps/docs/scripts/generate-error-reference.mjs @@ -106,8 +106,11 @@ export const TARGETS = { `including from extensions. Every other \`prisma\` command has its codes on the ${CLI_PAGE}.`, sharedCliNamespace: `This page and the ${CLI_PAGE} both have a \`CLI\` namespace, with different codes in each. ` + - "A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on this " + - "page. One from any other `prisma` command is on the other page.", + "The engine that runs every `prisma` command raises its own `CLI.*` codes for arguments, config " + + "loading, prompts, and consent, and those are on the CLI error reference even when the command " + + "was a Prisma ORM one, for example `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. " + + "The `CLI.*` codes on this page are the ones the Prisma ORM commands raise themselves. " + + "If a `CLI.*` code is not on this page, look on the other.", frontmatter: `--- title: Error reference description: The structured error codes of the Prisma ORM commands, runtime, and extensions, by namespace, with the condition that raises each one. @@ -130,8 +133,11 @@ metaDescription: The structured error codes of the Prisma ORM commands, runtime, `app can raise at runtime, are on the ${ORM_PAGE}.`, sharedCliNamespace: `This page and the ${ORM_PAGE} both have a \`CLI\` namespace, with different codes in each. ` + - "A `CLI.*` code from `prisma contract`, `prisma db`, `prisma migration`, or `prisma orm` is on the " + - "other page. One from any other `prisma` command is on this page.", + "The `CLI.*` codes on this page come from the engine that runs every `prisma` command, for " + + "arguments, config loading, prompts, and consent, whatever the command was, for example " + + "`CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. The Prisma ORM commands also raise " + + "`CLI.*` codes of their own, and those are on the Prisma ORM error reference. " + + "If a `CLI.*` code is not on this page, look on the other.", frontmatter: `--- title: Error reference description: The structured error codes of the Prisma CLI platform commands, by namespace, with the condition that raises each one. From b5dd2f469b2a769c0ced6b583dc55d52d34e0561 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 18:03:51 +0200 Subject: [PATCH 4/5] docs(errors): the CLI namespace note sits under the scope sentence A reader who arrives with CLI.CONFIG_SECTION_INVALID from prisma contract emit read the first paragraph, concluded the code was on the ORM page, and never reached the note below the namespace list. The note now follows the scope sentence directly and no longer says engine. Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- .../docs/content/docs/cli/error-reference.mdx | 4 +-- .../docs/orm/reference/error-reference.mdx | 4 +-- .../docs/scripts/generate-error-reference.mjs | 31 +++++++++++-------- scripts/generate-error-reference.test.ts | 7 +++-- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/apps/docs/content/docs/cli/error-reference.mdx b/apps/docs/content/docs/cli/error-reference.mdx index 15afec12673..aed4ce7475e 100644 --- a/apps/docs/content/docs/cli/error-reference.mdx +++ b/apps/docs/content/docs/cli/error-reference.mdx @@ -12,6 +12,8 @@ metaDescription: The structured error codes of the Prisma CLI platform commands, Every user-facing error the unified Prisma CLI emits is a structured envelope identified by a dotted `NAMESPACE.SUBCODE` code (see [Error Conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md) and [ADR 0003](https://github.com/prisma/prisma-cli/blob/main/docs/architecture/adrs/0003-structured-output-and-errors.md)). This page lists the codes from every `prisma` command except the Prisma ORM ones. The codes from `prisma contract`, `prisma db`, `prisma migration`, and `prisma orm`, and the codes your app can raise at runtime, are on the [Prisma ORM error reference](/orm/reference/error-reference). When an error prints a `docsUrl`, that link opens the code's entry on this page. This page is generated from the `prisma/prisma-cli` repository. +One exception: the `CLI.*` codes on this page come from the command-line layer that every `prisma` command runs through, for its arguments, for loading `prisma.config.ts`, for prompts, and for consent. They are on this page even when you ran a Prisma ORM command. `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit` is one of them. The Prisma ORM commands also raise `CLI.*` codes of their own, and those are on the [Prisma ORM error reference](/orm/reference/error-reference). If a `CLI.*` code is not on this page, it is on the other. + Recognize an error programmatically by running with `--json` and matching on `error.code` in the emitted envelope — never on message text. Envelopes carry `message`, and optionally `why`, `fix`, `where`, `meta`, `cause`, `nextActions`, and `docsUrl`. Most codes on this page are expected failures. Some are warn-severity diagnostics that ride a successful run: the command completes and exits `0`, and the diagnostic carries the code (the entry says so where it applies). The process exit-code contract is in [Error Conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md). @@ -32,8 +34,6 @@ Namespaces on this page: - [`SERVICE`](#service): Deployed service management (`prisma service`) - [`SKILLS`](#skills): Agent-skill delivery (`prisma skills`) -This page and the [Prisma ORM error reference](/orm/reference/error-reference) both have a `CLI` namespace, with different codes in each. The `CLI.*` codes on this page come from the engine that runs every `prisma` command, for arguments, config loading, prompts, and consent, whatever the command was, for example `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. The Prisma ORM commands also raise `CLI.*` codes of their own, and those are on the Prisma ORM error reference. If a `CLI.*` code is not on this page, look on the other. - ## AUTH ### AUTH.CREDENTIAL_WORKSPACE_MISMATCH [#AUTH.CREDENTIAL_WORKSPACE_MISMATCH] diff --git a/apps/docs/content/docs/orm/reference/error-reference.mdx b/apps/docs/content/docs/orm/reference/error-reference.mdx index 169515244f5..a1882e7dd5c 100644 --- a/apps/docs/content/docs/orm/reference/error-reference.mdx +++ b/apps/docs/content/docs/orm/reference/error-reference.mdx @@ -12,6 +12,8 @@ metaDescription: The structured error codes of the Prisma ORM commands, runtime, Every user-facing Prisma ORM error is a structured envelope identified by a dotted `NAMESPACE.SUBCODE` code (see [ADR 239](https://github.com/prisma/orm/blob/main/docs/architecture%20docs/adrs/ADR%20239%20-%20Errors%20are%20structural%20envelopes%20with%20dotted%20namespace%20codes.md) and [Error Handling](https://github.com/prisma/orm/blob/main/docs/Error%20Handling.md)). This page lists the codes from the Prisma ORM commands, which start with `prisma contract`, `prisma db`, `prisma migration`, and `prisma orm`, and the codes your app can raise at runtime, including from extensions. Every other `prisma` command has its codes on the [CLI error reference](/cli/error-reference). When an error prints a `docsUrl`, that link opens the code's entry on this page. This page is generated from the `prisma/orm` repository. +One exception: some `CLI.*` codes come from the command-line layer that every `prisma` command runs through, for its arguments, for loading `prisma.config.ts`, for prompts, and for consent. Those are on the [CLI error reference](/cli/error-reference) even when you ran a Prisma ORM command. `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit` is one of them. The `CLI.*` codes on this page are the ones the Prisma ORM commands raise themselves. If a `CLI.*` code is not on this page, it is on the other. + Recognize an error programmatically with `isStructuredError` from your facade package's `utils/structured-error` subpath (for example `@prisma/orm-postgres/utils/structured-error`) and match on `error.code`, never `instanceof`. Envelopes carry `message`, and optionally `why`, `fix`, `where`, `cause`, `docsUrl`, and the structured context each entry below lists as its **Payload**. The payload arrives on `error.meta` when the envelope was built by `structuredError` and on `error.details` when it was built by `runtimeError`; a few codes are raised both ways, so read whichever property the envelope carries. Exit codes (CLI): an expected structured failure exits `2`, a user abort exits `3`, and `1` is reserved for internal errors (bugs). Codes on this page exit `2` unless the entry says otherwise. @@ -40,8 +42,6 @@ Namespaces on this page: - [`SUPABASE`](#supabase): Supabase extension: config wiring and JWT handling - [`TESTKIT`](#testkit) -This page and the [CLI error reference](/cli/error-reference) both have a `CLI` namespace, with different codes in each. The engine that runs every `prisma` command raises its own `CLI.*` codes for arguments, config loading, prompts, and consent, and those are on the CLI error reference even when the command was a Prisma ORM one, for example `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. The `CLI.*` codes on this page are the ones the Prisma ORM commands raise themselves. If a `CLI.*` code is not on this page, look on the other. - ## CONFIG ### CONFIG.CONTRACT_MISSING [#CONFIG.CONTRACT_MISSING] diff --git a/apps/docs/scripts/generate-error-reference.mjs b/apps/docs/scripts/generate-error-reference.mjs index 9afefeba281..f690c1e019b 100644 --- a/apps/docs/scripts/generate-error-reference.mjs +++ b/apps/docs/scripts/generate-error-reference.mjs @@ -105,12 +105,12 @@ export const TARGETS = { "`prisma db`, `prisma migration`, and `prisma orm`, and the codes your app can raise at runtime, " + `including from extensions. Every other \`prisma\` command has its codes on the ${CLI_PAGE}.`, sharedCliNamespace: - `This page and the ${CLI_PAGE} both have a \`CLI\` namespace, with different codes in each. ` + - "The engine that runs every `prisma` command raises its own `CLI.*` codes for arguments, config " + - "loading, prompts, and consent, and those are on the CLI error reference even when the command " + - "was a Prisma ORM one, for example `CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. " + + "One exception: some `CLI.*` codes come from the command-line layer that every `prisma` command " + + "runs through, for its arguments, for loading `prisma.config.ts`, for prompts, and for consent. " + + `Those are on the ${CLI_PAGE} even when you ran a Prisma ORM command. ` + + "`CLI.CONFIG_SECTION_INVALID` from `prisma contract emit` is one of them. " + "The `CLI.*` codes on this page are the ones the Prisma ORM commands raise themselves. " + - "If a `CLI.*` code is not on this page, look on the other.", + "If a `CLI.*` code is not on this page, it is on the other.", frontmatter: `--- title: Error reference description: The structured error codes of the Prisma ORM commands, runtime, and extensions, by namespace, with the condition that raises each one. @@ -132,12 +132,12 @@ metaDescription: The structured error codes of the Prisma ORM commands, runtime, "from `prisma contract`, `prisma db`, `prisma migration`, and `prisma orm`, and the codes your " + `app can raise at runtime, are on the ${ORM_PAGE}.`, sharedCliNamespace: - `This page and the ${ORM_PAGE} both have a \`CLI\` namespace, with different codes in each. ` + - "The `CLI.*` codes on this page come from the engine that runs every `prisma` command, for " + - "arguments, config loading, prompts, and consent, whatever the command was, for example " + - "`CLI.CONFIG_SECTION_INVALID` from `prisma contract emit`. The Prisma ORM commands also raise " + - "`CLI.*` codes of their own, and those are on the Prisma ORM error reference. " + - "If a `CLI.*` code is not on this page, look on the other.", + "One exception: the `CLI.*` codes on this page come from the command-line layer that every " + + "`prisma` command runs through, for its arguments, for loading `prisma.config.ts`, for prompts, " + + "and for consent. They are on this page even when you ran a Prisma ORM command. " + + "`CLI.CONFIG_SECTION_INVALID` from `prisma contract emit` is one of them. " + + `The Prisma ORM commands also raise \`CLI.*\` codes of their own, and those are on the ${ORM_PAGE}. ` + + "If a `CLI.*` code is not on this page, it is on the other.", frontmatter: `--- title: Error reference description: The structured error codes of the Prisma CLI platform commands, by namespace, with the condition that raises each one. @@ -234,10 +234,15 @@ function replaceNamespaceList(body, target) { return description ? `- ${link}: ${description}` : `- ${link}`; }); const list = ["Namespaces on this page:", "", ...items, ""]; - if (namespaces.includes("CLI")) list.push(target.sharedCliNamespace, ""); const firstSection = body.search(/^## /m); - return `${body.slice(0, firstSection)}${list.join("\n")}\n${body.slice(firstSection)}`; + body = `${body.slice(0, firstSection)}${list.join("\n")}\n${body.slice(firstSection)}`; + if (!namespaces.includes("CLI")) return body; + + // The note answers the reader who arrived with a CLI.* code, so it sits + // under the scope sentence, before the upstream paragraphs and the list. + const firstParagraphEnd = body.search(/\n\s*\n/); + return `${body.slice(0, firstParagraphEnd)}\n\n${target.sharedCliNamespace}${body.slice(firstParagraphEnd)}`; } export function transform(target, markdown) { diff --git a/scripts/generate-error-reference.test.ts b/scripts/generate-error-reference.test.ts index 05954efa18e..08c574f8766 100644 --- a/scripts/generate-error-reference.test.ts +++ b/scripts/generate-error-reference.test.ts @@ -137,7 +137,8 @@ test("the shared CLI namespace is explained only when the source has a CLI secti const withoutCli = transform(TARGETS.cli, sourceWith({ namespaces: ["AUTH"] })).mdx; assert.ok(withCli.includes(TARGETS.cli.sharedCliNamespace)); - assert.ok(!withoutCli.includes("both have a `CLI` namespace")); + assert.ok(withCli.indexOf(TARGETS.cli.sharedCliNamespace) < withCli.indexOf("Namespaces on this page:")); + assert.ok(!withoutCli.includes("One exception:")); }); test("a reworded source intro still gets the scope sentence after its first paragraph, with a warning", () => { @@ -147,7 +148,9 @@ test("a reworded source intro still gets the scope sentence after its first para ); assert.ok( - mdx.includes(`Every error is a structured envelope.\n\n${TARGETS.orm.scope}\n\nMatch on`), + mdx.includes( + `Every error is a structured envelope.\n\n${TARGETS.orm.scope}\n\n${TARGETS.orm.sharedCliNamespace}\n\nMatch on`, + ), ); assert.equal(warnings.length, 1); assert.match(warnings[0], /This page lists every published code/); From 26d78d8e75aba149ea351e5893c4857dbe3d6465 Mon Sep 17 00:00:00 2001 From: willbot Date: Wed, 30 Sep 2026 18:05:32 +0200 Subject: [PATCH 5/5] docs(errors): the CLI note follows the scope sentence's paragraph, also when the scope sentence was inserted Co-Authored-By: Claude Fable 5.1 Signed-off-by: willbot Signed-off-by: Will Madden --- apps/docs/scripts/generate-error-reference.mjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/docs/scripts/generate-error-reference.mjs b/apps/docs/scripts/generate-error-reference.mjs index f690c1e019b..cd571637a05 100644 --- a/apps/docs/scripts/generate-error-reference.mjs +++ b/apps/docs/scripts/generate-error-reference.mjs @@ -240,9 +240,12 @@ function replaceNamespaceList(body, target) { if (!namespaces.includes("CLI")) return body; // The note answers the reader who arrived with a CLI.* code, so it sits - // under the scope sentence, before the upstream paragraphs and the list. - const firstParagraphEnd = body.search(/\n\s*\n/); - return `${body.slice(0, firstParagraphEnd)}\n\n${target.sharedCliNamespace}${body.slice(firstParagraphEnd)}`; + // directly under the paragraph that holds the scope sentence. + const scopeAt = body.indexOf(target.scope); + const from = scopeAt === -1 ? 0 : scopeAt; + const paragraphEnd = body.slice(from).search(/\n\s*\n/); + const at = paragraphEnd === -1 ? body.length : from + paragraphEnd; + return `${body.slice(0, at)}\n\n${target.sharedCliNamespace}${body.slice(at)}`; } export function transform(target, markdown) {