decolua/9router · error

Failed to list profiles: ${error}

Error message

Failed to list profiles: ${error}

What it means

Thrown by KiroService.listAvailableProfiles when the CodeWhisperer ListAvailableProfiles call (POST https://codewhisperer.<region>.amazonaws.com with the access token as Bearer) returns non-2xx; the AWS error body is embedded in the message. Without a profile list, no profileArn can be selected for the OAuth/IDC account.

Source

Thrown at src/lib/oauth/services/kiro.js:284

   */
  async listAvailableProfiles(accessToken, region = "us-east-1") {
    assertValidAwsRegion(region);
    const endpoint = `https://codewhisperer.${region}.amazonaws.com`;

    const response = await fetch(endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/x-amz-json-1.0",
        "x-amz-target": "AmazonCodeWhispererService.ListAvailableProfiles",
        "Authorization": `Bearer ${accessToken}`,
        "Accept": "application/json",
      },
      body: JSON.stringify({ maxResults: 10 }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(`Failed to list profiles: ${error}`);
    }

    const data = await response.json();
    const profiles = Array.isArray(data?.profiles) ? data.profiles : [];
    const arnOf = (p) => p?.arn || p?.profileArn || null;
    const match = profiles.find((p) => arnOf(p)?.split(":")[3] === region) || profiles[0];
    return arnOf(match);
  }

  /**
   * Validate an API key against the Amazon Q model catalog. A bearer-only call
   * to ListAvailableProfiles can return HTTP 200 with an empty list for an
   * arbitrary key, so it is not proof that the key can run inference.
   */
  async listAvailableApiKeyModels(apiKey, region = "us-east-1") {
    assertValidAwsRegion(region);
    const params = new URLSearchParams({ origin: "AI_EDITOR" });
    const endpoint = `https://q.${region}.amazonaws.com/ListAvailableModels?${params}`;

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Refresh the access token (refreshToken) before calling listAvailableProfiles — expired bearer tokens are the most common cause.
  2. Check the embedded AWS error body: AccessDenied/403 usually means the account lacks a CodeWhisperer/Amazon Q entitlement.
  3. Use a CodeWhisperer-supported region (assertValidAwsRegion already gates it, but the service may still reject it).
  4. Retry with backoff if the body shows throttling or a 5xx.

Example fix

// before: listing profiles with a possibly stale access token
const arn = await svc.listAvailableProfiles(account.accessToken, region);
// after: refresh first if near expiry
if (account.expiresIn && Date.now()/1000 > account.fetchedAt + account.expiresIn - 60) {
  account = await svc.refreshToken(account.refreshToken, account.providerSpecificData);
}
const arn = await svc.listAvailableProfiles(account.accessToken, region);
Defensive patterns

Strategy: try-catch

Validate before calling

function tokenUsable(account) {
  return typeof account?.accessToken === 'string' && account.accessToken.length > 0 &&
         (!account.expiresAt || Date.now() < account.expiresAt - 60_000);
}
if (!tokenUsable(account)) await doRefresh(account); // refresh before listing profiles

Type guard

function hasValidArn(arn) { return typeof arn === 'string' && arn.startsWith('arn:'); }

Try / catch

try {
  const arn = await svc.listAvailableProfiles(account.accessToken, region);
} catch (e) {
  if (/401|403|Unauthorized|AccessDenied/i.test(e.message)) {
    const fresh = await svc.refreshToken(account.refreshToken, account.providerSpecificData);
    return svc.listAvailableProfiles(fresh.accessToken, region); // one retry after refresh
  }
  if (/throttl/i.test(e.message)) return retryWithBackoff();
  throw e;
}

Prevention

When it happens

Trigger: The x-amz-target=AmazonCodeWhispererService.ListAvailableProfiles request returns !response.ok — expired/invalid access token (401/403), unsupported region for CodeWhisperer, missing entitlement for the account, or AWS 429/5xx.

Common situations: Access token expired because refresh wasn't performed before the profile listing; account has no CodeWhisperer/Amazon Q subscription; calling in a region where CodeWhisperer isn't available; network/proxy stripping the Authorization header.

Related errors


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