badges/shields · warning · NotFound
spec not found or unreadable
Error message
spec not found or unreadable
What it means
The Swagger validator badge's `transform` inspects schemaValidationMessages from validator.swagger.io. When exactly one error-level message equals `Can't read from file <specUrl>`, it throws NotFound 'spec not found or unreadable' — the validator could not fetch the OpenAPI/Swagger document at the given URL.
Source
Thrown at services/swagger/swagger.service.js:74
return this._requestJson({
url: 'https://validator.swagger.io/validator/debug',
schema,
options: {
searchParams: {
url: specUrl,
},
},
})
}
transform({ json, specUrl }) {
const valMessages = json.schemaValidationMessages
if (!valMessages || valMessages.length === 0) {
return { status: 'valid' }
} else if (valMessages.length === 1) {
const { message, level } = valMessages[0]
if (level === 'error' && message === `Can't read from file ${specUrl}`) {
throw new NotFound({ prettyMessage: 'spec not found or unreadable' })
}
}
if (valMessages.every(msg => msg.level === 'warning')) {
return { status: 'valid' }
}
return { status: 'invalid' }
}
async handle(_routeParams, { specUrl }) {
const json = await this.fetch({ specUrl })
const { status } = this.transform({ json, specUrl })
return this.constructor.render({ status })
}
}
View on GitHub (pinned to 766fd8bc89)
Solutions
- Open the spec URL in an external browser/incognito and confirm it returns the document with HTTP 200
- Publish the spec at a publicly reachable URL; the validator cannot access private networks or authenticated endpoints
- Fix URL typos and ensure the content-type/extension looks like JSON or YAML the validator can read
- Whitelist validator.swagger.io / fix TLS so the spec is fetchable; only after that check whether remaining validation messages indicate real spec errors
Example fix
// before /badge/swagger/v2/1.0/https://internal.example.com/local-api.json (404 externally) // after /badge/swagger/v2/1.0/https://api.example.com/public-openapi.json
Defensive patterns
Strategy: validation
Validate before calling
const specUrl = 'https://api.example.com/openapi.json';
const res = await fetch(specUrl);
if (!res.ok) throw new Error(`spec unreachable: HTTP ${res.status}`); // validator cannot read it either Type guard
const isPublicUrl = (u) => { try { const { hostname } = new URL(u); return !['localhost','127.0.0.1'].includes(hostname) && !/^(10|192\.168|172\.(1[6-9]|2\d|3[01]))\./.test(hostname); } catch { return false; } }; Try / catch
try {
return await swaggerBadge({ specUrl });
} catch (err) {
if (err prettyMessage === 'spec not found or unreadable') {
// check spec URL reachability/auth/TLS before retrying
} else throw err;
} Prevention
- Host the spec at a public, unauthenticated HTTPS URL (the remote validator must fetch it)
- Never use localhost/private-network URLs in badges
- Confirm the URL returns HTTP 200 with JSON/YAML content and a valid TLS certificate
- Avoid bot-protection rules that block validator.swagger.io's requests
When it happens
Trigger: Calling /swagger (e.g. /swagger/v2/1.0/https://host/spec.json) with a spec URL that returns 404, requires auth, blocks the validator's user agent, is on localhost/private network, or has invalid TLS.
Common situations: Spec hosted behind a login (intranet, private API); URL typo or file renamed; localhost/dev server URL used in a public badge; server rejecting external requests via firewall or bot protection (Cloudflare); self-signed certificate.
Related errors
AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30).
Data as JSON: /api/errors/c2692221d32bfdbc.
Report an issue: GitHub.