Budibase/budibase · warning

GitHub stars missing

Error message

GitHub stars missing

What it means

getStars fetches the GitHub repo metadata and expects `stargazers_count` in the JSON response. If the field is missing or not a number, it throws "GitHub stars missing" rather than returning invalid data. This guards the GetGitHubStarsResponse contract so downstream consumers always get a numeric star count.

Source

Thrown at packages/worker/src/api/controllers/global/github.ts:45

  try {
    const response = await fetch(GITHUB_REPO_URL, {
      headers: {
        Accept: "application/vnd.github+json",
        "User-Agent": USER_AGENT,
      },
      timeout: GITHUB_TIMEOUT_MS,
    })

    if (!response.ok) {
      throw new Error(`GitHub response: ${response.status}`)
    }

    const json = (await response.json()) as { stargazers_count?: number }
    const stars = json.stargazers_count

    if (typeof stars !== "number") {
      throw new Error("GitHub stars missing")
    }

    const value: GetGitHubStarsResponse = {
      stars,
      fetchedAt: new Date().toISOString(),
    }
    const toStore: StarsCacheEnvelope = {
      value,
      expiresAt: Date.now() + CACHE_TTL_MS,
    }

    await cache.store(CACHE_KEY, toStore, RETENTION_TTL_SECONDS, {
      useTenancy: false,
    })

    ctx.body = value
  } catch (err) {
    console.error("Failed to fetch GitHub stars", err)

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Check the HTTP status before parsing; handle 403/429 rate-limit responses separately
  2. Authenticate GitHub API calls with a GITHUB_TOKEN to raise the rate limit
  3. Verify the repository URL/owner/name configured for the stars endpoint is correct
  4. Retry with backoff if GitHub is having an incident; cache the last successful star count

Example fix

// before
const json = (await response.json()) as { stargazers_count?: number }
// after
if (!response.ok) {
  throw new Error(`GitHub API request failed: ${response.status}`)
}
const json = (await response.json()) as { stargazers_count?: number }
Defensive patterns

Strategy: type-guard

Validate before calling

const res = await fetch(githubApiUrl)
if (!res.ok) throw new Error(`GitHub API ${res.status}`)

Type guard

function hasStars(json: unknown): json is { stargazers_count: number } {
  return typeof json === "object" && json !== null &&
    typeof (json as { stargazers_count?: unknown }).stargazers_count === "number"
}

Try / catch

try {
  const stars = await getStars()
} catch (e) {
  const stars = cachedStars // fall back to last known value
}

Prevention

When it happens

Trigger: Calling getStars when the GitHub API returns a response body without a numeric `stargazers_count` — e.g. a rate-limit response ({"message": "API rate limit exceeded"}), an error object, a 404 body for a moved/renamed repo, or any non-200 response that still parses as JSON.

Common situations: GitHub API rate limiting (unauthenticated requests are capped at 60/hour per IP), the configured repo URL pointing at a nonexistent or renamed repository, GitHub incidents returning error payloads, or a proxy/firewall returning an HTML/JSON error page.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/9b656b94497c6b9f. Report an issue: GitHub.