{"record":{"id":"5011091df7dd23ef","repo":"remotion-dev/remotion","slug":"could-not-read-owner-repo-tree-message","errorCode":null,"errorMessage":"Could not read ${owner}/${repo}: ${tree.message ?? 'GitHub returned an invalid file tree.'}","messagePattern":"Could not read (.+?)/(.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-studio/src/load-github-repository.ts","lineNumber":155,"sourceCode":"\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}\n\n\tconst fileEntries = tree.tree.filter(\n\t\t(entry): entry is GitHubTreeEntry & {type: 'blob'} => entry.type === 'blob',\n\t);\n\tfor (const file of fileEntries) {\n\t\tvalidateRepositoryPath(file.path);\n\t}","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/remotion-dev/remotion/blob/10db9de07356446fb0edb3c3ae211369b693d18b/packages/browser-studio/src/load-github-repository.ts#L137-L173","documentation":"The GitHub trees API returned 2xx but the JSON body lacked tree.tree or tree.sha, so the response shape is unusable. This happens for repositories with no commits (HEAD has no tree yet), API-level message payloads, or unexpected/invalid responses. GitHub's message field is included when present; otherwise a generic 'invalid file tree' text is used.","triggerScenarios":"Calling loadGitHubRepository on a freshly created, completely empty repository (initialized with no README/commit); a GitHub API change or partial response; an intermediary (proxy/captive portal) returning 200 with non-GitHub JSON.","commonSituations":"Users pasting a link to a repo they just created but never pushed to; intermittent API weirdness during incidents; corporate proxies that intercept api.github.com.","solutions":["Verify the repository has at least one commit (an empty repo cannot be loaded)","Push an initial commit and retry","Retry later for transient API responses; check githubstatus.com if it persists"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await loadGitHubRepository({repoUrl});\n} catch (e) {\n  const msg = String((e as Error).message);\n  if (/invalid file tree/.test(msg) || msg.includes('Git Repository is empty')) {\n    // ask the user to push at least one commit, then retry\n  } else throw e;\n}","preventionTips":["Only share Browser Studio links to repositories that contain at least one commit","Retry once - GitHub occasionally returns partial API responses","Check githubstatus.com when invalid-tree errors persist across different repos"],"tags":["browser-studio","github","api","empty-repo"],"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-14T05:17:10.506Z"}