badges/shields · error · NotFound

not found

Error message

not found

What it means

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.

Source

Thrown at services/jetbrains/jetbrains-base.js:31

    return !pluginId.match(/^([0-9])+/)
  }

  static _cleanPluginId(pluginId) {
    const match = pluginId.match(/^([0-9])+/)
    if (match) {
      return match[0]
    }
    return pluginId
  }

  // xml
  static _validate(data, schema) {
    if (data['plugin-repository'] === '') {
      // Note the 'not found' response from JetBrains IntelliJ API is:
      // status code = 200,
      // body = <?xml version="1.0" encoding="UTF-8"?><plugin-repository></plugin-repository>
      // which is parsed to object = { 'plugin-repository': '' }
      throw new NotFound()
    }
    return super._validate(data, schema)
  }

  async fetchIntelliJPluginData({ pluginId, schema }) {
    const parserOptions = {
      parseTagValue: false,
      ignoreAttributes: false,
    }
    return this._requestXml({
      schema,
      url: `https://plugins.jetbrains.com/plugins/list?pluginId=${pluginId}`,
      parserOptions,
    })
  }

  // json
  _parseJson(buffer) {

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. 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').
  2. If the plugin was unpublished, remove the badge or use the archived plugin id if still served.
  3. Retry the badge after confirming the plugin page loads on plugins.jetbrains.com.

Example fix

// before
/jetbrains/plugin/d/1347-Scala
// after
/jetbrains/plugin/d/org.intellij.scala
Defensive patterns

Strategy: validation

Validate before calling

const JETBRAINS_PLUGIN_ID_RE = /^[A-Za-z0-9._-]+$/;
if (!JETBRAINS_PLUGIN_ID_RE.test(pluginId) || /^\d+-/.test(pluginId)) {
  throw new Error(`pluginId must be the XML id (e.g. org.intellij.scala), got: ${pluginId}`);
}

Type guard

function isNonEmptyPluginRepository(data) {
  return data && typeof data === 'object' && typeof data['plugin-repository'] === 'object' && data['plugin-repository'] !== '';
}

Try / catch

try {
  const data = await getJetBrainsPluginBadge(pluginId);
} catch (e) {
  if (e.name === 'NotFound') {
    renderFallback(`plugin '${pluginId}' not found on JetBrains marketplace`);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30). Data as JSON: /api/errors/8809f5fb89ace70a. Report an issue: GitHub.