Skip to content

feat(spectral): warn on rule names written as error.code (#163) - #164

Merged
clabonte merged 1 commit into
mainfrom
lint-error-reason-prose
Oct 15, 2026
Merged

clabonte merged 1 commit into
mainfrom
lint-error-reason-prose

Conversation

@clabonte

Copy link
Copy Markdown
Collaborator

Closes #163.

What

New Spectral rule specfuse-error-rule-name-in-code (warn). It flags a description or summary anywhere in the document that assigns or compares a snake_case rule name to code:

  • error.code = template_in_use
  • errors[0].code == 'page_size_over_limit'
  • `code`: `slot_already_booked`
  • "code": "delete_not_allowed"

Since #160 (compatibility.md §54), code is the HTTP status and the rule name goes in reason. Migrating the schema leaves prose like this behind, and nothing else checks it. Response examples are already covered: spectral:oas example validation rejects a string code.

Keeping it quiet on correct prose

  • Gate: the rule runs only when components.schemas.Error.properties.code is type: integer. A project still on the old string-code shape gets §54's migration note instead of warnings.
  • Underscore required: the matched value must contain one. That separates a rule name from code: integer or code = 409. The cost: a single-word rule name isn't caught.
  • No suffix matches: \b before code keeps status_code and reason_code out.

The rule is implemented as a custom function (functions/openapiErrorReasonProse.js), because the gate reads components while the matches come from anywhere in the document.

Verification (local, Spectral 6.16.2)

  • fixtures/error-reason-prose.yaml:
    • fires at exactly 4 places: an operation description, an operation summary, a nested 409 response description and an x-* block;
    • silent on /clean (error.reason = …), /status (code = 409, code: integer) and /otherCodes (status_code, reason_code, postal code).
  • fixtures/error-reason-prose-string-code.yaml: the same prose under a string code, with 0 findings (the gate holds).
  • hello-orders: 0 findings from the new rule, and the total is unchanged at 74.
    • In a copy, I injected error.code = order_locked into one referenced operation file. It reported exactly once, mapped to that file, so the multi-file $ref setup works.
  • Scaffold: a grep of templates/, examples/ and samples/ finds no prose the rule would flag.
  • Rule coverage: the harness passes on the fixtures. The new rule's given is $, so it always selects.
  • CI: a new example-regen.yml step asserts all of the above. I ran its assertions locally and they pass.

Docs

  • API Handbook §11 names the rule.
  • compatibility.md:
    • §51 item 2 no longer says the rule was never forwarded.
    • §54 migration step 1 points at the rule.
    • A new "Prose lint" paragraph in §54 records the gate and the underscore choice.

🤖 Generated with Claude Code

`specfuse-error-rule-name-in-code` (warn) flags a description or summary
that assigns or compares a snake_case rule name to `code`
(`error.code = template_in_use`, `"code": "x_y"`) when
`components.schemas.Error.properties.code` is an integer. Since §54 the
rule name belongs in `reason`; a schema migration leaves that prose behind.

- functions/openapiErrorReasonProse.js: the integer gate, and a match that
  needs an underscore in the value so `code: integer` / `code = 409` and
  `status_code` stay silent.
- fixtures error-reason-prose.yaml (4 firings, 3 silences) and
  error-reason-prose-string-code.yaml (the gate), asserted in
  example-regen.yml.
- API Handbook §11 names the rule; compatibility.md §51 item 2 and §54
  record it and point the migration at it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@clabonte
clabonte merged commit 95437d5 into main Oct 15, 2026
6 checks passed
@clabonte
clabonte deleted the lint-error-reason-prose branch October 15, 2026 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spectral: warn on rule names written as error.code when Error.code is the HTTP status

1 participant