An OpenAPI document can be perfectly valid JSON or YAML and still be a broken OpenAPI spec — the two are different questions. A syntax checker will happily accept a document with a typo'd schema reference or a duplicate operation ID; it's only when a code generator, mock server, or API gateway actually tries to use the spec that things fall apart, usually with an error message that points nowhere near the actual mistake. Here's what to check for.
Missing or malformed top-level fields
Every OpenAPI 3.x document needs an openapi version field (like 3.0.3, not just 3 — tooling that parses it strictly expects a full version string), an info object with both title and version, and a paths object. It's an easy set of fields to forget when you're hand-editing a spec that started life as a copy-paste from somewhere else, and their absence tends to produce confusing downstream errors rather than a clear "you forgot X."
Broken $ref references
This is the single most common real mistake in hand-written specs. OpenAPI documents reuse schemas by reference — {"$ref": "#/components/schemas/Pet"} — instead of repeating the same object shape everywhere. Rename a schema, or just typo it once while writing a new endpoint, and every reference to the old name becomes invisible until something actually tries to resolve it. A JSON/YAML validator has no way to catch this, since $ref is just a string value as far as the syntax is concerned — it takes a tool that understands OpenAPI's reference semantics to notice the target doesn't exist.
Duplicate operationId values
operationId is supposed to be unique across the entire document — it's what code generators use to name the method they generate for each endpoint. Two operations sharing an ID doesn't just violate the spec on paper; it means whatever client SDK gets generated from the document either silently overwrites one method with the other, or fails to generate at all, depending on the generator. This one is sneaky because it's easy to introduce by copy-pasting an existing operation as a starting point for a new endpoint and forgetting to change the ID.
Responses missing a description
Of everything in a response object, description is the one field the spec actually requires — schema, headers, and examples are all optional, but every response has to say what it means in words. It's also the field people skip most often, since it feels like documentation rather than structure. Strict validators reject a response object without one.
Path parameter mismatches
Two related mistakes show up constantly around path parameters:
- A path template like
/pets/{petId}with no matching parameter object declared forpetId— the placeholder exists in the URL but nothing in the spec says what it is, its type, or whether it's required. - A declared path parameter that doesn't set
required: true. This one trips people up because it feels redundant — of course a path segment is required, the URL literally can't resolve without it — but the spec still makes you say so explicitly, and omitting it is a validation error, not just a stylistic gap.
Checking for these before they cause problems
None of these mistakes will stop your spec from parsing — they only surface once something downstream tries to generate code, mock a server, or render documentation from the document, at which point the error is often several layers removed from the actual typo. Catching them at authoring time, before the spec goes anywhere, saves that entire debugging detour.
Try it yourself
Paste your spec into our OpenAPI Validator to check for all of the issues above — broken $refs, duplicate operation IDs, missing response descriptions, and path parameter mismatches — each reported with the exact location in the document. Once it's clean, browse it with the OpenAPI Viewer to see every endpoint, parameter, and schema rendered as a readable tree instead of raw JSON. Both run entirely in your browser; nothing you paste is ever uploaded.