decolua/9router · error · Error

Failed to fetch GitHub usage: ${error.message}

Error message

Failed to fetch GitHub usage: ${error.message}

What it means

This is the outer catch-all of getGitHubUsage: any error thrown inside the function (including errors 111 and 112) is re-thrown prefixed with 'Failed to fetch GitHub usage:'. The original message is preserved via error.message, so the root cause (missing token, HTTP error, JSON parse failure) is chained in the text.

Source

Thrown at open-sse/services/usage/github.js:87

          chat: {
            used: usedQuotas.chat || 0,
            total: monthlyQuotas.chat || 0,
            unlimited: false,
            resetAt,
          },
          completions: {
            used: usedQuotas.completions || 0,
            total: monthlyQuotas.completions || 0,
            unlimited: false,
            resetAt,
          },
        },
      };
    }

    return { message: "GitHub Copilot connected. Unable to parse quota data." };
  } catch (error) {
    throw new Error(`Failed to fetch GitHub usage: ${error.message}`);
  }
}

function formatGitHubQuotaSnapshot(quota) {
  if (!quota) return { used: 0, total: 0, unlimited: true };

  return {
    used: quota.entitlement - quota.remaining,
    total: quota.entitlement,
    remaining: quota.remaining,
    unlimited: quota.unlimited || false,
  };
}

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Strip the prefix and inspect error.message to find the root cause (missing token vs API error)
  2. If the cause is a missing/invalid token, re-run the GitHub OAuth authorization flow
  3. Guard the call in try/catch and render a 'reconnect GitHub' prompt instead of crashing the usage panel
  4. Ensure the upstream body is JSON — HTML error pages will fail at response.json()

Example fix

// before
const usage = await getGitHubUsage(token, data, proxy);
// after
let usage;
try {
  usage = await getGitHubUsage(token, data, proxy);
} catch (e) {
  usage = { error: true, message: e.message, reconnectNeeded: /access token/i.test(e.message) };
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!account?.accessToken) return { reconnect: true, quotas: null };

Try / catch

try {
  usage = await getGitHubUsage(token, data, proxy);
} catch (e) {
  // e.message is the prefixed chain: inspect inner cause
  const cause = e.message.replace(/^Failed to fetch GitHub usage: /, "");
  return { error: cause, reconnectNeeded: /access token|API error: 40/.test(cause) };
}

Prevention

When it happens

Trigger: Any failure path inside getGitHubUsage: falsy accessToken, non-OK upstream response, response.json() failing on a non-JSON body, or an unexpected runtime error while parsing quota_snapshots / quota_reset_date fields.

Common situations: Callers seeing this wrapper in logs/usage handlers; double wrapping when the usage handler itself adds another prefix; the inner cause being an expired token or upstream 4xx.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/f944aa4ae494d756. Report an issue: GitHub.