tinyhumansai/openhuman · error · Error

Failed to fetch repositories

Error message

Failed to fetch repositories

What it means

SmartIssuePicker repo loading: after confirming a GitHub connection exists in listConnections() (ACTIVE/CONNECTED, toolkit contains 'github' - otherwise the distinct 'NOT_CONNECTED' error throws earlier), it runs composioExecute('GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER', {}). If the Composio action returns successful:false, it throws res.error when present, else this fallback string. The subsequent parsing handles array or {repositories:[]} response shapes.

Solutions

  1. Reconnect GitHub via Connections so Composio gets a fresh token
  2. Log or inspect res.error - when the fallback fires it means Composio returned no error detail at all
  3. Retry after a minute if rate limiting is plausible
  4. Confirm the account actually grants repository read access (enterprise/SSO auth)

Example fix

// before
if (!res.successful) throw new Error(res.error ?? 'Failed to fetch repositories');

// after - keep NOT_CONNECTED distinct and surface Composio's detail when it exists
if (!res.successful) {
  const detail = res.error ?? 'Failed to fetch repositories';
  throw new Error(`Composio GITHUB_LIST_REPOSITORIES: ${detail}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the connection before loading, so NOT_CONNECTED and action failure stay distinct
const conns = await listConnections();
const gh = conns.connections?.find(c =>
  c.toolkit.toLowerCase().includes('github') &&
  (c.status === 'ACTIVE' || c.status === 'CONNECTED'));
if (!gh) { setReposError('Connect GitHub first'); return; }

Try / catch

try {
  const res = await composioExecute('GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER', {});
  if (!res.successful) throw new Error(res.error ?? 'Failed to fetch repositories');
  // parse res.data ...
} catch (err) {
  const msg = err instanceof Error ? err.message : String(err);
  if (msg === 'NOT_CONNECTED') setReposError('Connect GitHub in Connections first');
  else setReposError(msg);
}

Prevention

When it happens

Trigger: The Composio GitHub action itself fails: revoked/expired GitHub token on the connection, GitHub API error or rate limit, Composio-side outage, or the connected account lacking repo read scope.

Common situations: Token revoked in GitHub settings while Composio still lists the connection ACTIVE; secondary rate limits hitting bulk repo listing; org SSO not authorized for the token; intermittent Composio 5xx surfacing as successful:false with no error string.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/a63e15358d51cc11. Report an issue: GitHub.

Appendix: source

Thrown at app/src/components/skills/SmartIssuePicker.tsx:93

  // each onRepoSelect captures its own id and bails out of any state
  // update once a newer selection has superseded it.
  const selectionSeqRef = useRef(0);

  // ── Load repos via Composio ─────────────────────────────────────────
  const loadRepos = useCallback(async () => {
    setReposLoading(true);
    setReposError(null);
    try {
      const connections = await listConnections();
      const ghConn = connections.connections?.find(
        c =>
          c.toolkit.toLowerCase().includes('github') &&
          (c.status === 'ACTIVE' || c.status === 'CONNECTED')
      );
      if (!ghConn) throw new Error('NOT_CONNECTED');

      const res = await composioExecute('GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER', {});
      if (!res.successful) throw new Error(res.error ?? 'Failed to fetch repositories');

      const raw = res.data;
      let repoList: ComposioGhRepo[] = [];
      const items = Array.isArray(raw)
        ? raw
        : ((raw as Record<string, unknown>)?.repositories ?? []);
      if (Array.isArray(items)) {
        repoList = (items as Record<string, unknown>[]).map(r => ({
          owner: String((r.owner as Record<string, unknown>)?.login ?? r.owner ?? ''),
          repo: String(r.name ?? ''),
          fullName: String(
            r.full_name ?? `${(r.owner as Record<string, unknown>)?.login ?? r.owner}/${r.name}`
          ),
          private: r.private as boolean | undefined,
          defaultBranch: r.default_branch as string | undefined,
        }));
      }

View on GitHub (pinned to 7491200858)