{"record":{"id":"6c134a04b643b71c","repo":"remotion-dev/remotion","slug":"could-not-read-owner-repo-await-getrespon","errorCode":null,"errorMessage":"Could not read ${owner}/${repo}: ${await getResponseError(treeResponse)}","messagePattern":"Could not read (.+?)/(.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-studio/src/load-github-repository.ts","lineNumber":148,"sourceCode":"\nexport const loadGitHubRepository = async ({\n\tonProgress,\n\trepoUrl,\n\tsignal,\n}: {\n\tonProgress?: (progress: LoadGitHubRepositoryProgress) => void;\n\trepoUrl: string;\n\tsignal?: AbortSignal;\n}): Promise<VirtualProject> => {\n\tconst {owner, repo} = parseGitHubRepositoryUrl(repoUrl);\n\tonProgress?.({phase: 'reading-repository'});\n\n\tconst treeResponse = await fetch(\n\t\t`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/git/trees/HEAD?recursive=1`,\n\t\t{signal},\n\t);\n\tif (!treeResponse.ok) {\n\t\tthrow new Error(\n\t\t\t`Could not read ${owner}/${repo}: ${await getResponseError(treeResponse)}`,\n\t\t);\n\t}\n\n\tconst tree = (await treeResponse.json()) as GitHubTreeResponse;\n\tif (!tree.tree || !tree.sha) {\n\t\tthrow new Error(\n\t\t\t`Could not read ${owner}/${repo}: ${tree.message ?? 'GitHub returned an invalid file tree.'}`,\n\t\t);\n\t}\n\n\tconst treeSha = tree.sha;\n\n\tif (tree.truncated) {\n\t\tthrow new Error(\n\t\t\t`${owner}/${repo} has too many files for Browser Studio to load.`,\n\t\t);\n\t}","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/remotion-dev/remotion/blob/10db9de07356446fb0edb3c3ae211369b693d18b/packages/browser-studio/src/load-github-repository.ts#L130-L166","documentation":"loadGitHubRepository calls GET https://api.github.com/repos/{owner}/{repo}/git/trees/HEAD?recursive=1 without authentication and throws on any non-2xx response, appending GitHub's own error message from the JSON body (or the status text). Common statuses: 404 for a missing or private repository, 403 for exceeding GitHub's anonymous rate limit (60 requests/hour per IP), and 5xx for GitHub incidents.","triggerScenarios":"Loading a repo URL that does not exist or is private (404 Not Found); loading many repos in quick succession from one IP until the anonymous quota is exhausted (403 rate limit); GitHub API incidents returning 5xx.","commonSituations":"Typos in owner/repo; private repositories (the API is unauthenticated so they are invisible); shared NAT/office networks where the per-IP anonymous quota is consumed by others; embedding a Browser Studio link that many users open at once.","solutions":["Verify owner/repo spelling and that the repository is public","If the message mentions the rate limit, wait for GitHub's anonymous quota (60 requests/hour per IP) to reset","Retry after a few minutes for transient GitHub 5xx errors","Check https://www.githubstatus.com/ during suspected API incidents"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const res = await fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`);\nif (res.status === 404) throw new Error('Repository does not exist or is private');\nif (res.status === 403 || res.status === 429) throw new Error('GitHub anonymous rate limit reached - wait before retrying');\nif (!res.ok) throw new Error(`GitHub API returned ${res.status}`);","typeGuard":null,"tryCatchPattern":"const backoff = (ms: number) => new Promise((r) => setTimeout(r, ms));\ntry {\n  await loadGitHubRepository({repoUrl});\n} catch (e) {\n  const msg = String((e as Error).message);\n  if (msg.includes('Not Found')) throw new Error('Repo is private or does not exist - check owner/repo');\n  if (/rate limit/i.test(msg)) await backoff(60_000); // anonymous quota window, then retry\n  else throw e;\n}","preventionTips":["Verify the repo is public and the owner/repo spelling is correct before loading","Cache or throttle loadGitHubRepository calls to conserve the 60 req/h anonymous GitHub API quota per IP","Treat 403 with 'rate limit' in the message differently from 404 - one waits, the other is a typo"],"tags":["browser-studio","github","api","network","rate-limit"],"backgroundTag":"github-api-request-failed","analyzedSha":"10db9de07356446fb0edb3c3ae211369b693d18b","analyzedAt":"2026-08-22T21:45:17.748Z","contentChangedAt":"2026-08-22T21:45:17.748Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}