chatboxai/chatbox · warning · GitHubApiError

Not found: ${url}

Error message

Not found: ${url}

What it means

GitHubApiError with status 404, thrown by githubFetch when the GitHub API responds 404 for the requested URL. It is distinct from generic API errors and rate-limit errors so callers can branch on 'missing resource' specifically. getCached is consulted first; the 404 is only set after a real network call.

Source

Thrown at src/main/skills/github-fetcher.ts:87

    super(message)
    this.name = 'GitHubApiError'
  }
}

async function githubFetch<T>(url: string): Promise<T> {
  const cached = getCached<T>(url)
  if (cached !== undefined) return cached

  const response = await fetch(url, {
    headers: {
      'User-Agent': USER_AGENT,
      Accept: 'application/vnd.github.v3+json',
    },
  })

  if (!response.ok) {
    if (response.status === 404) {
      throw new GitHubApiError(`Not found: ${url}`, 404)
    }
    if (response.status === 403) {
      throw new GitHubApiError('GitHub API rate limit exceeded. Try again later.', 403)
    }
    throw new GitHubApiError(`GitHub API error: ${response.status} ${response.statusText}`, response.status)
  }

  const data = (await response.json()) as T
  setCache(url, data)
  return data
}

async function fetchRepoTree(owner: string, repo: string): Promise<GitHubTreeResponse | null> {
  const url = `${GITHUB_API_BASE}/repos/${owner}/${repo}/git/trees/HEAD?recursive=1`
  const result = await githubFetch<GitHubTreeResponse>(url)
  if (!Array.isArray(result?.tree)) {
    log.warn(`Unexpected tree response shape for ${owner}/${repo}`)
    return null

View on GitHub (pinned to 81571269ad)

Solutions

  1. Verify owner/repo spelling and that the repo exists and is public (or provide a GITHUB token for private repos).
  2. If using HEAD ref, confirm the repo has a default branch; if using an explicit ref, confirm it exists.
  3. Branch on GitHubApiError status===404 to show 'skill repository not found' rather than a generic failure.
  4. Cache negative results briefly to avoid hammering GitHub with the same bad URL.

Example fix

// caller
try { await githubFetch(url) } catch (e) {
  if (e instanceof GitHubApiError && e.status === 404) { showSkillNotFound(); return }
  throw e
}
Defensive patterns

Strategy: try-catch

Validate before calling

const repoExists = await checkRepoExists(owner, repo)
if (!repoExists) return null

Type guard

function isGitHub404(e: unknown): e is GitHubApiError { return e instanceof GitHubApiError && e.status === 404 }

Try / catch

try { return await githubFetch(url) } catch (e) { if (isGitHub404(e)) { showSkillNotFound(url); return null } throw e }

Prevention

When it happens

Trigger: GET against a repo, tree, or content URL whose owner/repo/ref/path is wrong or inaccessible: typo in owner/repo, the repo is private and the request is unauthenticated, the branch/tag (HEAD ref) does not exist, or the file path inside the tree is wrong.

Common situations: Skill catalog pointing at a renamed/deleted repo; default branch changed from 'main' to something else while the fetch uses HEAD (usually fine) vs a hardcoded ref; private repo fetched without a token; case-sensitivity on owner/repo names.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/e4e1a7ee9ddf66b0. Report an issue: GitHub.