{"record":{"id":"0dd7f3ed33e753c7","repo":"jackwener/OpenCLI","slug":"homebrew-popular","errorCode":null,"errorMessage":"homebrew popular","messagePattern":"homebrew popular","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"error","filePath":"clis/homebrew/popular.js","lineNumber":38,"sourceCode":"    domain: 'formulae.brew.sh',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'type', default: 'formula', help: `Package type (${TYPES.join(' / ')})` },\n        { name: 'window', default: '30d', help: `Time window (${WINDOWS.join(' / ')})` },\n        { name: 'limit', type: 'int', default: 30, help: 'Max rows (1-500)' },\n    ],\n    columns: ['rank', 'token', 'type', 'installs', 'percent', 'window', 'url'],\n    func: async (args) => {\n        const type = requireOneOf(args.type, TYPES, 'type');\n        const window = requireOneOf(args.window, WINDOWS, 'window');\n        const limit = requireBoundedInt(args.limit, 30, 500);\n        const path = type === 'cask' ? 'cask-install' : 'install';\n        const url = `${BREW_BASE}/analytics/${path}/${window}.json`;\n        const body = await brewFetch(url, 'homebrew popular');\n        const items = Array.isArray(body?.items) ? body.items : [];\n        if (!items.length) {\n            throw new EmptyResultError('homebrew popular', `Homebrew analytics returned no items for ${type}/${window}.`);\n        }\n        return items.slice(0, limit).map((row, i) => {\n            const token = String(type === 'cask' ? row.cask : row.formula ?? '').trim();\n            const detailPath = type === 'cask' ? 'cask' : 'formula';\n            return {\n                rank: row.number != null ? Number(row.number) : i + 1,\n                token,\n                type,\n                installs: parseInstallCount(row.count),\n                percent: row.percent != null ? Number(row.percent) : null,\n                window,\n                url: token ? `https://formulae.brew.sh/${detailPath}/${encodeURIComponent(token)}` : '',\n            };\n        });\n    },\n});\n","sourceCodeStart":20,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/homebrew/popular.js#L20-L55","documentation":"brewFetch wraps any fetch/transport failure for the analytics request in CommandExecutionError labeled 'homebrew popular'. The label is also the fallback context string passed when the Homebrew analytics endpoint (formulae.brew.sh) cannot be reached, returns a non-OK status, or responds with malformed JSON.","triggerScenarios":"The GET to `${BREW_BASE}/analytics/install|cask-install/<window>.json` throws a network error, returns HTTP != 200/404/429, or the body fails JSON.parse.","commonSituations":"Offline or corporate-proxy-blocked network, formulae.brew.sh (GitHub Pages) outage, transient 5xx, or DNS failure in CI containers.","solutions":["Check network reachability of https://formulae.brew.sh from this machine","Retry after a short wait — the API is static GitHub Pages and outages are brief","Check proxy/firewall settings if behind a corporate network","Catch CommandExecutionError and fall back to cached/last-known analytics data"],"exampleFix":"// before\nconst body = await brewFetch(url, 'homebrew popular');\n// after\nlet body;\ntry {\n  body = await brewFetch(url, 'homebrew popular');\n} catch (err) {\n  body = await readCachedAnalytics() ?? throwWith Hint(err);\n}","handlingStrategy":"retry","validationCode":"const url = `${BREW_BASE}/analytics/${path}/${window}.json`;\nconst head = await fetch(url, { method: 'HEAD' }).catch(() => null);\nif (!head || !head.ok) throw new Error(`formulae.brew.sh unreachable (status ${head?.status ?? 'network error'})`);","typeGuard":null,"tryCatchPattern":"async function fetchWithRetry(url, label, retries = 3) {\n  for (let i = 0; i < retries; i++) {\n    try {\n      return await brewFetch(url, label);\n    } catch (err) {\n      if (i === retries - 1) throw err;\n      await new Promise(r => setTimeout(r, 1000 * 2 ** i));\n    }\n  }\n}","preventionTips":["Retry with exponential backoff — the API is static GitHub Pages and briefly flaky","Cache the last successful analytics JSON as a fallback","Check DNS/proxy config in CI before scraping","Respect the bundled user-agent and avoid hammering the endpoint"],"tags":["network","http","homebrew"],"backgroundTag":"http-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}