Most “OpenAPI 3.1 specification” validation failures aren’t subtle schema problems. They’re usually boring things: a missing required field, a wrong data type, a bad $ref, or a schema pattern that validators don’t expect.
And the frustrating part? You can have an API that “looks right” in Swagger documentation, but your OpenAPI validation still fails because a single object doesn’t match what the spec requires.
So here’s a practical way to get a spec to pass validation: start small, validate early, and fix the specific errors you get (not the ones you guess).
Start with a minimal valid OpenAPI 3.1 specification
This snippet is intentionally tiny. It still includes the required top-level structure so validators don’t immediately bail.
openapi: 3.1.0
info:
title: Example API
version: 1.0.0
paths:
/ping:
get:
responses:
"200":
description: OK
Why this works: openapi, info, paths, and at least one response are the minimum you need for a usable document. Validators often fail earlier when these basics are missing.
Required vs optional fields: the part that trips everyone
Here’s the mental model that helps: OpenAPI validators enforce the shape of the spec. Optional fields can be absent. Required fields can’t. A lot of API spec errors look like “type mismatch,” but the real cause is usually “this object isn’t in the expected place.”
- Always required (top-level):
openapi,info,paths. - Often required in operations: every operation must have
responses. - Inside responses: each response entry needs a
description.
When you get a validation error, don’t just patch fields. Check that the field lives in the right object. For example, a responses block under the wrong key won’t magically “become valid.”

Common OpenAPI validation errors (and the fixes)
Below are the errors I see most when people write YAML API spec files and then run OpenAPI validation tooling.
| Error | Typical cause | Fix |
|---|---|---|
Missing required property ... | You omitted a required object like info or paths, or you forgot responses on an operation. | Add the required field in the correct location (and ensure its children are also present where required). |
Schema is invalid / Incorrect type. Expected ... | A schema keyword is placed where OpenAPI expects something else (e.g., example vs examples, wrong object vs array). | Compare the schema node to the spec for that keyword and fix the node type. Don’t “almost match.” |
Invalid $ref / Could not resolve pointer | Your $ref path is wrong, or the referenced component doesn’t exist (including a JSON pointer typo). | Verify the target exists. For JSON pointers, count slashes carefully. Prefer consistent ids in components/schemas. |
OneOf/anyOf/... must be an array | You wrote oneOf or anyOf as a single object instead of a list. | Wrap schema alternatives in an array: oneOf: [ ... ]. |
discriminator ... mapping ... invalid | You used discriminator without the required fields, or the discriminator value doesn’t line up with the schemas. | Make sure discriminator.propertyName exists and that mapping (if you use it) points to valid schema refs. |
Additional properties not allowed | You added fields that the validator flags as illegal in that context. | Remove the extra fields or move them to the correct object. Validators can be strict. |
$ref usage: it’s not “just a pointer”
$ref does two things: it tells the validator where the schema lives, and it changes how the validator checks constraints.
Two gotchas that show up constantly:
- Wrong JSON pointer:
#/components/schemas/Petis not the same as#/components/schemas/pet. It’s also not the same as#/components/schema/Pet. - Not resolving across files: external refs require correct file paths and valid documents. If you move files, your refs silently break.
If your spec fails with “could not resolve reference,” stop touching schema logic. Fix the ref target first. Everything else becomes noise until references resolve.
Discriminators: make them consistent with your schema
OpenAPI supports discriminator for polymorphic schemas. The validator will check that your discriminator configuration makes sense for the schema structure.
Common failure pattern: you pick a propertyName that doesn’t actually exist in the variants, or you map values to schemas that don’t extend/fit the same inheritance base.
A safer approach:
- Define a base schema that represents “the union.”
- Define variant schemas that are intended targets for the discriminator.
- Use
discriminator.propertyNamethat your actual payloads will include. - If you use
discriminator.mapping, map every discriminator value you emit to a schema ref.
Validators don’t magically infer your intent. They only check structural consistency.
oneOf / anyOf: structure matters more than meaning
oneOf and anyOf look similar in practice, but validators treat them as schema-composition keywords. That means they must be arrays of schemas.
Broken (common):
schema:
oneOf:
type: object
Fix:
schema:
oneOf:
- type: object
properties: { id: { type: string } }
- type: object
properties: { email: { type: string } }
Also: if you combine oneOf/anyOf with $ref, keep the alternatives strictly schema objects or refs. Mixing “raw shapes” and refs is fine as long as every element is a valid schema.
Tooling that actually catches mistakes before publishing
Don’t rely on the renderer in Swagger documentation. It’s helpful, but it’s not your enforcement mechanism.
Use a validator in CI:
- Spectral: linting rules for API specs. Good for catching style and structural issues early.
- swagger-parser: a parser/validator that resolves refs and reports errors. Great for “does this document actually resolve?” failures.
- Redocly CLI: OpenAPI linting and breaking-change checks. Useful when you want repeatable checks for OpenAPI validation.
Workflow I trust:
- Start from the minimal valid spec snippet.
- Run parsing/validation after every meaningful edit (especially after moving YAML around).
- Fix errors in the order the tools report them. The first failure often causes the rest.
When you validate, point your eyes at the node the tool references. Most “mystery errors” are just you editing the wrong indentation level in YAML API spec files.
One last gotcha: don’t treat “validated” as “correct”
A spec can pass OpenAPI validation and still describe behavior you don’t actually implement. Validation checks structure and constraints, not your product logic.
But if your OpenAPI 3.1 specification doesn’t pass validation, your documentation toolchain and client generators will keep hurting you. Fix that layer first.
Now do this tonight: take your current YAML API spec, run one of the tools above, and fix the first error they report. Then re-run. That loop beats guessing every time.
References: OpenAPI v3.1.0 specification, Swagger specification overview, Red Hat: What is OpenAPI.