justjavac/wechat-miniapp-radar · warning · Error

HTTP ${response.status}

Error message

HTTP ${response.status}

What it means

Thrown by fetchJson() in lib/enrichment.ts when an HTTP response is non-OK; it raises a bare `HTTP <status>` carrying only the status code. fetchJson() is the internal helper used to pull GitHub repo metadata and npm registry data during signal collection, with a 10s AbortController timeout (an abort surfaces as a different AbortError, not this message). The public collector collectResourceSignal() wraps every fetchJson() call in try/catch and converts the thrown error into a CollectedSignal with ok:false and the message in .error, so it never escapes to top-level code.

Source

Thrown at lib/enrichment.ts:94

    return parts[1] ?? null;
  } catch {
    return null;
  }
}

async function fetchJson<T>(url: string, headers: HeadersInit = {}) {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 10000);

  try {
    const response = await fetch(url, {
      headers: {
        "user-agent": "miniprogram-radar",
        ...headers
      },
      signal: controller.signal
    });
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return (await response.json()) as T;
  } finally {
    clearTimeout(timeout);
  }
}

async function fetchHead(url: string) {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 8000);

  try {
    const response = await fetch(url, {
      method: "HEAD",
      headers: {
        "user-agent": "miniprogram-radar"
      },
      redirect: "follow",
      signal: controller.signal

View on GitHub (pinned to 02a010ecea)

Solutions

  1. Set GITHUB_TOKEN to raise GitHub limits from 60 to about 5000 req/hour (collectResourceSignal already attaches it as Bearer when present).
  2. For 404s, correct or remove the resource URL in data/resources.yaml then run npm run generate.
  3. For transient 403-rate-limit or 5xx, retry with backoff or reduce runEnrichment({ limit }).
  4. Always read the returned CollectedSignal.ok/.error rather than letting fetchJson propagate.

Example fix

// before
const repo = await fetchJson<GitHubRepo>(url); // throws 'HTTP 403'

// after (the pattern collectResourceSignal already uses)
try {
  const repo = await fetchJson<GitHubRepo>(url, headers);
} catch (error) {
  return { ok: false, error: error instanceof Error ? error.message : String(error) };
}
Defensive patterns

Strategy: try-catch

Validate before calling

const needsGithubToken = resources.some(r => r.url.startsWith('https://github.com/'));
if (needsGithubToken && !process.env.GITHUB_TOKEN) {
  console.warn('GITHUB_TOKEN unset; GitHub fetches may 403 after 60 req/hour');
}

Try / catch

try {
  const data = await fetchJson<T>(url, headers);
} catch (error) {
  const message = error instanceof Error ? error.message : String(error); // e.g. 'HTTP 403'
  return { ok: false, payload: {}, error: message } satisfies CollectedSignal;
}

Prevention

When it happens

Trigger: GitHub repos API returns 403 (unauthenticated rate limit of 60 req/hour, or an expired GITHUB_TOKEN); 404 for a renamed or deleted repo or npm package; 401 for a bad token; 5xx from the registry; a registry/site returning a non-2xx status for an otherwise valid URL.

Common situations: Running enrichment locally without GITHUB_TOKEN and hitting the 60/hr limit; a tracked repo renamed or moved; npm package unpublished; flaky 5xx during a bulk run; GITHUB_TOKEN expired but still set in env.

Related errors


AI-assisted analysis of justjavac/wechat-miniapp-radar@02a010ecea (2026-08-12). Data as JSON: /api/errors/522eea4a7a002342. Report an issue: GitHub.