remotion-dev/remotion · error · Error

Could not read ${owner}/${repo}: ${await getResponseError(tr

Error message

Could not read ${owner}/${repo}: ${await getResponseError(treeResponse)}

What it means

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.

Source

Thrown at packages/browser-studio/src/load-github-repository.ts:148

export const loadGitHubRepository = async ({
	onProgress,
	repoUrl,
	signal,
}: {
	onProgress?: (progress: LoadGitHubRepositoryProgress) => void;
	repoUrl: string;
	signal?: AbortSignal;
}): Promise<VirtualProject> => {
	const {owner, repo} = parseGitHubRepositoryUrl(repoUrl);
	onProgress?.({phase: 'reading-repository'});

	const treeResponse = await fetch(
		`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/git/trees/HEAD?recursive=1`,
		{signal},
	);
	if (!treeResponse.ok) {
		throw new Error(
			`Could not read ${owner}/${repo}: ${await getResponseError(treeResponse)}`,
		);
	}

	const tree = (await treeResponse.json()) as GitHubTreeResponse;
	if (!tree.tree || !tree.sha) {
		throw new Error(
			`Could not read ${owner}/${repo}: ${tree.message ?? 'GitHub returned an invalid file tree.'}`,
		);
	}

	const treeSha = tree.sha;

	if (tree.truncated) {
		throw new Error(
			`${owner}/${repo} has too many files for Browser Studio to load.`,
		);
	}

View on GitHub (pinned to 10db9de073)

Solutions

  1. Verify owner/repo spelling and that the repository is public
  2. If the message mentions the rate limit, wait for GitHub's anonymous quota (60 requests/hour per IP) to reset
  3. Retry after a few minutes for transient GitHub 5xx errors
  4. Check https://www.githubstatus.com/ during suspected API incidents
Defensive patterns

Strategy: retry

Validate before calling

const res = await fetch(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`);
if (res.status === 404) throw new Error('Repository does not exist or is private');
if (res.status === 403 || res.status === 429) throw new Error('GitHub anonymous rate limit reached - wait before retrying');
if (!res.ok) throw new Error(`GitHub API returned ${res.status}`);

Try / catch

const backoff = (ms: number) => new Promise((r) => setTimeout(r, ms));
try {
  await loadGitHubRepository({repoUrl});
} catch (e) {
  const msg = String((e as Error).message);
  if (msg.includes('Not Found')) throw new Error('Repo is private or does not exist - check owner/repo');
  if (/rate limit/i.test(msg)) await backoff(60_000); // anonymous quota window, then retry
  else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of remotion-dev/remotion@10db9de073 (2026-08-22). Data as JSON: /api/errors/6c134a04b643b71c. Report an issue: GitHub.