{"record":{"id":"c4e80256ad5fe9f5","repo":"badges/shields","slug":"invalid-rank","errorCode":null,"errorMessage":"invalid rank","messagePattern":"invalid rank","errorType":"exception","errorClass":"InvalidResponse","httpStatus":424,"severity":"error","filePath":"services/gem/gem-rank.service.js","lineNumber":80,"sourceCode":"    if (period === 'rt') {\n      endpoint = 'total_ranking.json'\n      schema = totalSchema\n    } else {\n      endpoint = 'daily_ranking.json'\n      schema = dailySchema\n    }\n\n    return this._requestJson({\n      url: `http://bestgems.org/api/v1/gems/${gem}/${endpoint}`,\n      schema,\n    })\n  }\n\n  async handle({ period, gem }) {\n    const json = await this.fetch({ period, gem })\n    const rank = period === 'rt' ? json[0].total_ranking : json[0].daily_ranking\n    if (rank == null) {\n      throw new InvalidResponse({ prettyMessage: 'invalid rank' })\n    }\n    return this.constructor.render({ period, rank })\n  }\n}\n","sourceCodeStart":62,"sourceCodeEnd":85,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/gem/gem-rank.service.js#L62-L85","documentation":"Thrown in GemRankService.handle when the BestGems API response does not yield a usable ranking value. The service reads json[0].total_ranking (for 'rt') or json[0].daily_ranking, and if rank == null an InvalidResponse 'invalid rank' is thrown.","triggerScenarios":"Requesting a gem rank badge where the upstream BestGems API returns an empty array, an array whose first element lacks the expected ranking field, or null ranking for that gem/period combination.","commonSituations":"Very new or very obscure gems that are unranked in BestGems; BestGems API schema changes or downtime returning malformed payloads; wrong period token (only 'rt' and 'dw' are supported) causing the wrong field to be read.","solutions":["Confirm the gem is ranked at bestgems.org for the requested period","Use the correct period token ('rt' for realtime total, 'dw' for daily)","Check the BestGems API response for the gem to see if ranking fields are present","Treat as transient upstream flakiness and retry later if BestGems was recently updated"],"exampleFix":"// before\n/gem/rtd/my-unranked-gem\n// after\n/gem/rtd/rails  // use a ranked gem, or handle absence","handlingStrategy":"try-catch","validationCode":"const data = await fetch(`https://bestgems.org/api/v1/gems/${gem}/${period === 'rt' ? 'total_ranking' : 'daily_ranking'}.json`).then(r => r.json());if (!Array.isArray(data) || data[0]?.[period === 'rt' ? 'total_ranking' : 'daily_ranking'] == null) { console.warn('gem is unranked'); }","typeGuard":"const hasRank = (json, period) => Array.isArray(json) && json.length > 0 && json[0]?.[period === 'rt' ? 'total_ranking' : 'daily_ranking'] != null;","tryCatchPattern":"try { return await gemRankBadge({ period, gem }); } catch (e) { if (String(e.message).includes('invalid rank')) { return renderBadge('unranked'); } throw e; }","preventionTips":["Only embed rank badges for gems you know are ranked on bestgems.org","Use supported period tokens ('rt' or 'dw')","Render an 'unranked' fallback badge for new/obscure gems"],"tags":["rubygems","invalid-response","upstream-api"],"backgroundTag":"unexpected-upstream-response","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}