oas-validator
oas-validator is the validation package from the OAS-Kit monorepo. It accepts an already-parsed OpenAPI object, checks that it follows OpenAPI 3.0.x structure and rules, optionally resolves references and runs lint rules, then resolves with a mutated options object containing `valid`, warnings, metadata, and context. It is an assertion-based CommonJS library that stops at the first structural error rather than collecting a full diagnostic report.
Use it to preserve an existing OAS-Kit and OpenAPI 3.0 workflow, especially when its resolver options are already wired in. For a new validator or any OpenAPI 3.1 document, choose a maintained alternative with current spec support and typed APIs.
Use it if
- You maintain an OAS-Kit pipeline and need the validator that shares its resolver, linter, and option conventions
- Your documents are strictly OpenAPI 3.0.x and first-error validation is acceptable
- You need both Promise and Node-style callback entry points in older CommonJS code
- You want optional external reference resolution and can control the resolver's file or network access
- You use OpenAPI 3.1: the source requires the version string to start with 3.0. and implements the OpenAPI 3.0 Schema Object rules
- You want all validation errors in one run: the package README says assertion-based structural validation stops on the first error, while only lint mode can report multiple warnings
- You need a current TypeScript or ESM experience: 5.0.8 is CommonJS, publishes no declarations or export map, and was released in 2021
- You validate untrusted specs with remote references: `resolve`, custom handlers, fetch options, and a source URL can trigger file or network retrieval, so the caller must enforce protocol and destination policy
- You want a self-contained lightweight validator: the package brings eight direct dependencies, including the OAS-Kit resolver, linter, schema walker, YAML parser, and assertion library
Setup reality
Install with npm install oas-validator, then require it from CommonJS. There are no native builds, credentials, peer dependencies, or required config files, but the input must already be a JavaScript object. Reading JSON means handling fs and JSON.parse yourself; YAML input requires a parser such as yaml before validation. The main `validate(openapi, options)` call returns a Promise, or accepts a third Node-style callback. Pass a real mutable options object, not undefined: the implementation writes `valid`, `context`, `warnings`, `operationIds`, `openapi`, `cache`, and metadata onto it. A successful Promise resolves to that same options object, not to a boolean or a cleaned document. A failure rejects on the first structural problem; the most useful location is commonly on `error.options.context` or the original options context stack. Setting `lint: true` loads the bundled default linter and can produce multiple warnings, but lint violations ultimately reject validation rather than merely decorating a successful result. External references are not resolved unless requested. With `resolve: true`, set `source` so relative references have a base and consider a controlled `fetch`, `fetchOptions`, `agent`, cache, or protocol handlers. This can create network and filesystem access that is inappropriate for arbitrary uploaded specs. The hard compatibility limit is OpenAPI 3.0.x: despite registry wording that says 3.x, the source explicitly rejects 3.1. There are no bundled TypeScript declarations, and the last package release was in 2021, so expect to write a local type shim and pin behavior in tests.
Patterns
Validate an OpenAPI 3.0 objectvalidate-object
const validator = require('oas-validator');
const options = {};
try {
const result = await validator.validate(openapiDocument, options);
console.log(result.valid); // true
} catch (error) {
console.error(error.message);
}The Promise resolves with the mutated options object, not a boolean or a replacement document.
Read and validate a JSON specificationvalidate-json-file
const fs = require('node:fs/promises');
const validator = require('oas-validator');
const text = await fs.readFile('./openapi.json', 'utf8');
const document = JSON.parse(text);
const options = { source: './openapi.json', text };
await validator.validate(document, options);source supplies a base for relative references; text lets metadata count input lines.
Parse YAML before validationvalidate-yaml-file
const fs = require('node:fs/promises');
const YAML = require('yaml');
const validator = require('oas-validator');
const text = await fs.readFile('./openapi.yaml', 'utf8');
const document = YAML.parse(text);
await validator.validate(document, { source: './openapi.yaml', text });oas-validator accepts an object; install and invoke a YAML parser yourself for file text.
Report the first failing locationreport-error-context
const options = {};
try {
await validator.validate(document, options);
} catch (error) {
const context = error.options?.context ?? options.context ?? [];
console.error(error.message);
console.error('Location:', context.at(-1) ?? '#/');
}Structural validation intentionally stops at the first error, so this is not a complete issue list.
Use the callback formuse-callback
const validator = require('oas-validator');
validator.validate(document, {}, (error, options) => {
if (error) {
console.error(error.message);
return;
}
console.log('valid:', options.valid);
});Providing the third argument switches from a returned Promise to callback delivery.
Run bundled lint rules during validationlint-document
const options = { lint: true, lintLimit: 20 };
try {
await validator.validate(document, options);
} catch (error) {
console.error(error.message);
for (const warning of options.warnings) console.error(warning);
}Lint mode can collect multiple warnings, but lint violations cause the validation Promise to reject.
Skip selected lint rulesskip-lint-rules
const options = {
lint: true,
lintSkip: ['operation-tags', 'info-contact'],
lintLimit: 50,
};
await validator.validate(document, options);Rule names belong to the bundled oas-linter version; pin dependencies and verify names before relying on skips.
Resolve relative external referencesresolve-external-refs
const options = {
resolve: true,
source: '/srv/specs/openapi.yaml',
cache: {},
};
await validator.validate(document, options);Resolution may read files or fetch URLs. Do not enable it for untrusted documents without restricting allowed locations.
Control network fetching for external referencescustomize-ref-fetch
const options = {
resolve: true,
source: 'https://specs.example.com/openapi.yaml',
fetch: async (url, init) => {
if (new URL(url).hostname !== 'specs.example.com') throw new Error('blocked ref host');
return fetch(url, { ...init, signal: AbortSignal.timeout(5000) });
},
};
await validator.validate(document, options);Host checks and timeouts are caller responsibilities when specifications can point at remote resources.
Run the cheap shape checkcheck-document-shape
const validator = require('oas-validator');
if (!Boolean(validator.microValidate(document, {}))) {
throw new Error('missing openapi, info, or paths');
}
await validator.validate(document, {});microValidate only checks a few required properties and can return the paths object; it is not standards validation.
Ignore default and type mismatchesallow-lax-defaults
const options = { laxDefaults: true };
await validator.validate(document, options);This relaxes a real schema consistency check. Prefer fixing invalid defaults unless compatibility with an existing spec requires it.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| @apidevtools/swagger-parser | npm | You want a maintained parser, dereferencer, and validator for Swagger 2.0 and OpenAPI 3.0 |
| openapi-schema-validator | npm | You want schema validation with a modern release line and straightforward error arrays |
| @redocly/openapi-core | npm | You need OpenAPI 3.1-aware linting, bundling, rules, and Redocly tooling integration |
| ibm-openapi-validator | npm | You want configurable lint rules and a fuller report for API governance in CI |