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
- Reconnect GitHub via Connections so Composio gets a fresh token
- Log or inspect res.error - when the fallback fires it means Composio returned no error detail at all
- Retry after a minute if rate limiting is plausible
- 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
- Keep the GitHub Composio connection fresh - an ACTIVE status does not prove the token still works
- Always fall back to res.error; the generic string only fires when Composio returned no detail
- Handle NOT_CONNECTED separately so users get a 'connect first' message, not a fetch failure
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
- Failed to fetch repositories
- Failed to list branches
- GMAIL_FETCH_EMAILS error
- Apify run finished with status
- Backend error for DELETE
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)