Common OpenAPI Errors and How to Fix Them

Common OpenAPI errors with the exact messages parsers print: missing $ref pointers, duplicate operation ids, undeclared path parameters, YAML indentation.

On this page

Most OpenAPI errors fall into four groups: YAML or JSON that does not parse, version fields written as numbers, $ref pointers that point at nothing, and objects that break a rule of the specification, such as a response without a description or a path parameter that is not marked required. Each group produces a recognisable message. Find yours in the table below, jump to its section, and apply the fix. Every message quoted here is real output from @apidevtools/swagger-parser 12.1.0 and the js-yaml parser it uses, captured by running deliberately broken copies of one small Orders API spec.

Message starts withWhat is wrongSection
bad indentation of a mapping entryA YAML line is indented to the wrong depthYAML syntax
tab characters must not be used in indentationA tab instead of spacesYAML syntax
duplicated mapping keyThe same key twice in one objectYAML syntax
Openapi version number must be a stringopenapi: 3.0 without quotesVersion fields
API version number must be a stringinfo.version: 1.0 without quotesVersion fields
Missing $ref pointerA reference to a component that does not existBroken references
must have required property 'description'A response without a descriptionSchema violations
must NOT have fewer than 1 propertiesAn empty responses objectSchema violations
required must be equal to one of the allowed valuesA path parameter not marked required: trueSchema violations
type must be stringA type array in an OpenAPI 3.0 documentSchema violations
must NOT have duplicate itemsThe same parameter listed twiceSchema violations
Duplicate operation idTwo operations share an operationIdRule violations
is missing path parameter(s) forA {template} in the path with no parameterRule violations
Messages from swagger-parser 12.1.0 and js-yaml. Other tools word them differently but report the same problems.

The test spec is a 3.0.3 document with a GET /v1/orders/{orderId} operation, a path parameter, 200 and 404 responses, and an Order schema in components. Each section below changes one thing in it.

YAML syntax errors

These stop everything. Until the file parses, no tool can tell you anything about OpenAPI rules, so fix them first. js-yaml prints the line and column in parentheses and draws a caret under the spot.

Text
YAMLException: bad indentation of a mapping entry (11:18)

  8 |       responses:
  9 |         "200":
 10 |          description: ok
 11 |           content: {}
-----------------------^
description is indented 9 spaces and content 10. Sibling keys must start in the same column.

The fix for bad indentation is to line up sibling keys. The caret often lands on the second of two siblings, because the parser only notices the problem when the next key does not match. Check the line above it as well. Most editors can show whitespace characters; turn that on, and the off-by-one space becomes visible.

tab characters must not be used in indentation means what it says: YAML forbids tabs for indentation. Configure your editor to insert spaces in .yaml files and replace existing tabs. duplicated mapping key appears when an object has the same key twice, for example two title lines under info or the same path pasted twice under paths. YAML would otherwise keep the last value and silently drop the first, so the parser refuses. Delete or merge the duplicate.

JSON specs fail differently. A trailing comma or a comment makes the JSON parser stop with a position number in the message. JSON allows neither, so remove them, or switch the file to YAML if you want comments.

Version fields written as numbers

Text
SyntaxError: Openapi version number must be a string (e.g. "3.0.0") not a number.
SyntaxError: API version number must be a string (e.g. "1.0.0") not a number.

In YAML, openapi: 3.0 and version: 1.0 are read as numbers, not strings. The first message comes from the openapi field and the second from info.version. Both fields must be strings. Write the full version, openapi: 3.0.3, which YAML reads as a string because it has two dots, or quote the value: version: "1.0". Quoting is the safer habit, because version: 1.10 would otherwise become the number 1.1.

A related message, Unsupported OpenAPI version, means the parser does not know the value in the openapi field. swagger-parser 12.1.0 accepts 3.0.0 to 3.0.4 and 3.1.0 to 3.1.2. Check for typos such as 3.0 or 3.1, and check that your tools support the version you declared before you bump it.

Broken references

Text
Missing $ref pointer "#/components/schemas/Orders". Token "Orders" does not exist.

The parser followed the pointer one segment at a time and failed at the token it names. Here the schema is called Order and the reference says Orders. Pointers are case-sensitive, so order and Order are different names too. Read the pointer left to right against your file and stop at the first segment that does not exist.

  • Typo or plural mismatch in the component name, as above.
  • The wrong section for the version. Swagger 2.0 keeps schemas in #/definitions/; OpenAPI 3.x keeps them in #/components/schemas/. A spec half-converted from 2.0 often mixes the two. The Swagger vs OpenAPI guide lists the other moved sections.
  • A slash inside a key. JSON Pointer escapes / as ~1 and ~ as ~0, so a reference to the path /orders/{id} is written #/paths/~1orders~1{id}.
  • A relative file reference such as ./schemas/order.yaml that resolves from a different directory than you expect. Paths resolve relative to the file that contains the $ref, not the directory you ran the tool from.

APIForge treats this case leniently so you can still explore the API. When it loads a spec with a local reference that does not resolve, it swaps in a placeholder object whose description reads Unmodeled schema reference followed by the pointer, and loads the rest. If you see that text in the OpenAPI validator workspace, search your file for the pointer it names.

Schema violations

Once a file parses and its references resolve, validators check it against the JSON Schema published for its OpenAPI version. swagger-parser reports these as Swagger schema validation failed (it uses that heading for OpenAPI 3 files too), followed by one line per failed check. Each line starts with a JSON Pointer to the location, with / in path names escaped as ~1.

Text
Swagger schema validation failed.
  #/paths/~1v1~1orders~1{orderId}/get/responses/404 must have required property 'description'
  #/paths/~1v1~1orders~1{orderId}/get/responses/404 must have required property '$ref'
  #/paths/~1v1~1orders~1{orderId}/get/responses/404 must match exactly one schema in oneOf
One real problem, three lines of output.

Read only the first line. The other two are echoes. A response entry can be either a Response Object or a Reference Object, so the validator tries both: the first fails because description is missing, the second because there is no $ref, and the oneOf then fails because neither matched. The fix is to add description: Not found. The same pattern explains the long lists you get for parameters, where every allowed value of in gets its own complaint.

A path parameter that is not required

Text
#/paths/~1v1~1orders~1{orderId}/get/parameters/0/required must be equal to one of the allowed values

The OpenAPI Specification says that when in is path, required must be present and must be true. A path segment cannot be optional; /v1/orders/ with nothing after it is a different URL. Set required: true. If the parameter really is optional, the operation needs two paths, such as /v1/orders and /v1/orders/{orderId}.

A type array in OpenAPI 3.0

Text
#/paths/~1v1~1orders~1{orderId}/get/responses/200/content/application~1json/schema/properties/id/type must be string

OpenAPI 3.0 accepts a single string for type. type: [string, "null"] is OpenAPI 3.1 syntax. Either write type: string with nullable: true, or move the whole document to openapi: 3.1.0. The response schema guide covers when a field should be nullable at all.

Duplicate parameters and empty responses

must NOT have duplicate items (items ## 0 and 1 are identical) means a parameters list contains the same object twice, often after copy and paste. A parameter is identified by name plus location, so delete one copy. must NOT have fewer than 1 properties on a responses object means it is empty. The specification requires at least one response code; add the success response the operation returns.

Rule violations a schema cannot express

Some rules involve more than one place in the document, so the JSON Schema for OpenAPI cannot check them. Two that people hit often are operationId uniqueness and path parameters that do not match the path template. swagger-parser checks both for Swagger 2.0 files and prints messages like these:

Text
Validation failed. Duplicate operation id 'getOrder'
Validation failed. /paths/v1/orders/{orderId}/get is missing path parameter(s) for {orderId}
Validation failed. /paths/v1/orders/{orderId}/get has a path parameter named "itemId", but there is no corresponding {itemId} in the path string

For a duplicate operationId, rename one of the operations. The specification says the id must be unique among all operations and is case-sensitive. Generated clients usually turn operationIds into method names, so a duplicate tends to surface as a compile error in the SDK rather than in the spec. A verb plus the resource, such as listOrders and getOrder, keeps them unique.

For a missing path parameter, add a parameter with in: path, required: true and the exact name used in braces, or declare it once at the path level so every operation under that path inherits it. For the reverse case, a path parameter with no matching {name} in the template, remove the parameter or fix the spelling in the path.

One more cross-reference rule from the OpenAPI Specification: templated paths with the same hierarchy but different parameter names, such as /v1/orders/{id} and /v1/orders/{orderId}, must not exist, because they are identical to a router. Pick one name and merge the operations.

A quick order for fixing a broken file

Work from the outside in

  1. Make it parse

    Fix YAML or JSON syntax first. Nothing else is reported until the file loads.

  2. Fix the version fields

    Quote openapi and info.version, and confirm the openapi value is one your tools support.

  3. Resolve every $ref

    Fix the first missing pointer the parser names, then run again; one bad reference can hide others behind it.

  4. Clear schema violations from the top

    Read the first line of each group, fix it, and rerun. The echo lines disappear with it.

  5. Run a linter for cross-document rules

    Duplicate operationIds and path parameter mismatches need a rule-based linter on OpenAPI 3 files.

A file that clears all five steps is valid, which is not the same as well designed. Run it through the API quality score for naming, versioning and error-response coverage, or compare it with the patterns in the bad OpenAPI example.

Frequently asked questions

Many OpenAPI objects can be either the real object or a $ref, and the schema expresses that with oneOf. When neither branch matches, the validator reports why each branch failed and then that the oneOf failed. The first line is usually the real problem.

The OpenAPI 3.0.3 specification says they must be quoted, as in "200", for compatibility between JSON and YAML. JavaScript parsers turn an unquoted 200 into the string "200" anyway, so the file may load, but tools in other languages can read it as an integer key. Quote them.

Validators that only check the file against the OpenAPI JSON Schema cannot see it, because uniqueness spans the whole document. swagger-parser, for example, runs those rule checks only for Swagger 2.0. A linter with an operationId uniqueness rule will catch it.

Sources

  1. OpenAPI Specification 3.1.0: operationId, path templating and parametersOpenAPI Initiative
  2. OpenAPI Specification 3.0.3: Responses Object and Schema ObjectOpenAPI Initiative
  3. Swagger Parser options: validate.schema and validate.specAPIDevTools