{"record":{"id":"8809f5fb89ace70a","repo":"badges/shields","slug":"not-found-8809f5","errorCode":null,"errorMessage":"not found","messagePattern":"not found","errorType":"exception","errorClass":"NotFound","httpStatus":404,"severity":"error","filePath":"services/jetbrains/jetbrains-base.js","lineNumber":31,"sourceCode":"    return !pluginId.match(/^([0-9])+/)\n  }\n\n  static _cleanPluginId(pluginId) {\n    const match = pluginId.match(/^([0-9])+/)\n    if (match) {\n      return match[0]\n    }\n    return pluginId\n  }\n\n  // xml\n  static _validate(data, schema) {\n    if (data['plugin-repository'] === '') {\n      // Note the 'not found' response from JetBrains IntelliJ API is:\n      // status code = 200,\n      // body = <?xml version=\"1.0\" encoding=\"UTF-8\"?><plugin-repository></plugin-repository>\n      // which is parsed to object = { 'plugin-repository': '' }\n      throw new NotFound()\n    }\n    return super._validate(data, schema)\n  }\n\n  async fetchIntelliJPluginData({ pluginId, schema }) {\n    const parserOptions = {\n      parseTagValue: false,\n      ignoreAttributes: false,\n    }\n    return this._requestXml({\n      schema,\n      url: `https://plugins.jetbrains.com/plugins/list?pluginId=${pluginId}`,\n      parserOptions,\n    })\n  }\n\n  // json\n  _parseJson(buffer) {","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/jetbrains/jetbrains-base.js#L13-L49","documentation":"The JetBrains IntelliJ base service throws a bare NotFound when the JetBrains plugin repository API responds with HTTP 200 but an empty `<plugin-repository>` XML body, which parses to `{ 'plugin-repository': '' }`. JetBrains signals 'plugin not found' this way instead of a 404, so the service translates it into a NotFound error. The comment in the source documents this quirk explicitly.","triggerScenarios":"Requesting plugin data (ratings/downloads/version) via fetchIntelliJPluginData for a pluginId that the JetBrains repository does not know — the API returns an empty plugin-repository element with status 200 and _validate throws NotFound.","commonSituations":"Wrong pluginId format in the badge URL (must be the XML id like 'org.intellij.scala', not the numeric plugin id or the plugin name); plugin unpublished/removed from the marketplace; typos or case mismatch in the id.","solutions":["Copy the exact plugin XML id from the plugin's marketplace page (the id in its URL, e.g. /plugin/1347-Scala --> 'org.intellij.scala').","If the plugin was unpublished, remove the badge or use the archived plugin id if still served.","Retry the badge after confirming the plugin page loads on plugins.jetbrains.com."],"exampleFix":"// before\n/jetbrains/plugin/d/1347-Scala\n// after\n/jetbrains/plugin/d/org.intellij.scala","handlingStrategy":"validation","validationCode":"const JETBRAINS_PLUGIN_ID_RE = /^[A-Za-z0-9._-]+$/;\nif (!JETBRAINS_PLUGIN_ID_RE.test(pluginId) || /^\\d+-/.test(pluginId)) {\n  throw new Error(`pluginId must be the XML id (e.g. org.intellij.scala), got: ${pluginId}`);\n}","typeGuard":"function isNonEmptyPluginRepository(data) {\n  return data && typeof data === 'object' && typeof data['plugin-repository'] === 'object' && data['plugin-repository'] !== '';\n}","tryCatchPattern":"try {\n  const data = await getJetBrainsPluginBadge(pluginId);\n} catch (e) {\n  if (e.name === 'NotFound') {\n    renderFallback(`plugin '${pluginId}' not found on JetBrains marketplace`);\n  } else throw e;\n}","preventionTips":["Use the plugin's XML id from its marketplace URL, never the numeric id or display name","Verify the plugin page exists on plugins.jetbrains.com before adding the badge","Remember JetBrains returns 200 with an empty repository body for unknown plugins"],"tags":["jetbrains","not-found","plugin","api-quirk"],"backgroundTag":"upstream-resource-not-found","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}