{"record":{"id":"c2692221d32bfdbc","repo":"badges/shields","slug":"spec-not-found-or-unreadable","errorCode":null,"errorMessage":"spec not found or unreadable","messagePattern":"spec not found or unreadable","errorType":"exception","errorClass":"NotFound","httpStatus":404,"severity":"warning","filePath":"services/swagger/swagger.service.js","lineNumber":74,"sourceCode":"    return this._requestJson({\n      url: 'https://validator.swagger.io/validator/debug',\n      schema,\n      options: {\n        searchParams: {\n          url: specUrl,\n        },\n      },\n    })\n  }\n\n  transform({ json, specUrl }) {\n    const valMessages = json.schemaValidationMessages\n    if (!valMessages || valMessages.length === 0) {\n      return { status: 'valid' }\n    } else if (valMessages.length === 1) {\n      const { message, level } = valMessages[0]\n      if (level === 'error' && message === `Can't read from file ${specUrl}`) {\n        throw new NotFound({ prettyMessage: 'spec not found or unreadable' })\n      }\n    }\n    if (valMessages.every(msg => msg.level === 'warning')) {\n      return { status: 'valid' }\n    }\n    return { status: 'invalid' }\n  }\n\n  async handle(_routeParams, { specUrl }) {\n    const json = await this.fetch({ specUrl })\n    const { status } = this.transform({ json, specUrl })\n    return this.constructor.render({ status })\n  }\n}\n","sourceCodeStart":56,"sourceCodeEnd":89,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/swagger/swagger.service.js#L56-L89","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n/badge/swagger/v2/1.0/https://internal.example.com/local-api.json  (404 externally)\n// after\n/badge/swagger/v2/1.0/https://api.example.com/public-openapi.json","handlingStrategy":"validation","validationCode":"const specUrl = 'https://api.example.com/openapi.json';\nconst res = await fetch(specUrl);\nif (!res.ok) throw new Error(`spec unreachable: HTTP ${res.status}`); // validator cannot read it either","typeGuard":"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; } };","tryCatchPattern":"try {\n  return await swaggerBadge({ specUrl });\n} catch (err) {\n  if (err prettyMessage === 'spec not found or unreadable') {\n    // check spec URL reachability/auth/TLS before retrying\n  } else throw err;\n}","preventionTips":["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"],"tags":["swagger","not-found","url-unreachable","spec"],"backgroundTag":"url-unreachable","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}