{"record":{"id":"4544b526f0e561bf","repo":"tinyhumansai/openhuman","slug":"failed-to-list-branches","errorCode":null,"errorMessage":"Failed to list branches","messagePattern":"Failed to list branches","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/components/skills/inputs/BranchPicker.tsx","lineNumber":72,"sourceCode":"      setError(null);\n      return;\n    }\n    const [owner, repoName] = repo.split('/');\n    if (!owner || !repoName) {\n      setBranches([]);\n      return;\n    }\n    const seq = ++requestSeqRef.current;\n    setLoading(true);\n    setError(null);\n    try {\n      const res = await composioExecute('GITHUB_LIST_BRANCHES', {\n        owner,\n        repo: repoName,\n        per_page: 100,\n      });\n      if (seq !== requestSeqRef.current) return;\n      if (!res.successful) throw new Error(res.error ?? 'Failed to list branches');\n      // Composio wraps GitHub branch data in a few different shapes\n      // (details, data.details, branches, items, direct array under data) —\n      // probe the same way DevWorkflowPanel does.\n      const raw = res.data;\n      let list: GhBranch[] = [];\n      if (Array.isArray(raw)) {\n        list = raw as GhBranch[];\n      } else if (raw && typeof raw === 'object') {\n        const obj = raw as Record<string, unknown>;\n        const dataObj = obj.data as Record<string, unknown> | undefined;\n        const arr =\n          (obj.details as unknown[] | undefined) ??\n          (dataObj?.details as unknown[] | undefined) ??\n          (obj.branches as unknown[] | undefined) ??\n          (obj.items as unknown[] | undefined) ??\n          (dataObj as unknown[] | undefined);\n        if (Array.isArray(arr)) {\n          list = arr as GhBranch[];","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/components/skills/inputs/BranchPicker.tsx#L54-L90","documentation":"BranchPicker load: calls composioExecute('GITHUB_LIST_BRANCHES', { owner, repo: repoName, per_page: 100 }) guarded by a request sequence counter (stale responses for a changed repo are dropped, not errors). If the action returns successful:false it throws res.error when present, else 'Failed to list branches'. Parsing afterwards tolerates several Composio wrapper shapes (details, data.details, branches, items, bare array).","triggerScenarios":"The GITHUB_LIST_BRANCHES action fails: owner/repo pair wrong or inaccessible (private repo the token cannot read), token revoked/expired, GitHub rate limit, or the repo has no default access via the connected account.","commonSituations":"Typo in the repo name assembled by a parent picker; private/org repo the Composio connection was never granted; rapid repo switching where an in-flight request fails; per_page: 100 hiding branches on huge repos is NOT this error - that is silent truncation.","solutions":["Confirm owner/repo are correct and the connected GitHub account can see the repo","Reconnect GitHub via Composio if the token was revoked","Inspect res.error in the network/console for GitHub's message before retrying","Retry the selection after rate limits cool down"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate owner/repo shape before firing the Composio action\nif (!owner.trim() || !repoName.trim() || /[\\/\\s]/.test(repoName)) {\n  setError('Select a valid owner/repo first');\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const res = await composioExecute('GITHUB_LIST_BRANCHES', { owner, repo: repoName, per_page: 100 });\n  if (seq !== requestSeqRef.current) return; // stale response for a different repo - not an error\n  if (!res.successful) throw new Error(res.error ?? 'Failed to list branches');\n  // unwrap details / data.details / branches / items / array ...\n} catch (err) {\n  setError(err instanceof Error ? err.message : String(err));\n}","preventionTips":["Ensure the GitHub connection actually grants read on private/org repos before listing branches","Respect the request-sequence guard: a failure for an abandoned repo selection should not paint the UI","Prefer res.error over the fallback string; log it even when the UI shows a generic message"],"tags":["composio","github","branches","integration","skills"],"backgroundTag":"third-party-integration-action-failed","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}