decolua/9router · error

Failed to list models: ${error}

Error message

Failed to list models: ${error}

What it means

listAvailableModels POSTs to the CodeWhisperer AmazonCodeWhispererService.ListAvailableModels endpoint with the access token and profileArn. If the upstream responds with a non-2xx status, the response body (an AWS JSON error document) is read as text and rethrown as 'Failed to list models: <body>'. The thrown message therefore carries the authoritative AWS error (e.g. AccessDeniedException, expired token).

Source

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

    const target = "AmazonCodeWhispererService.ListAvailableModels";

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

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

    const data = await response.json();
    return (data.models || []).map(m => ({
      id: m.modelId,
      name: m.modelName || m.modelId,
      description: m.description,
      rateMultiplier: m.rateMultiplier,
      rateUnit: m.rateUnit,
      maxInputTokens: m.tokenLimits?.maxInputTokens || 0,
    }));
  }

  /**
   * Fetch user email from access token (optional, for display)
   */
  extractEmailFromJWT(accessToken) {
    try {

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Read the AWS error body after 'Failed to list models: ' — AccessDenied/Unauthorized means refresh the access token (or re-run OAuth) before retrying.
  2. Verify profileArn is correct and non-null; fetch it via listAvailableProfiles if unknown.
  3. Refresh/re-authenticate the credential to obtain a valid accessToken for the CodeWhisperer surface.
  4. Retry with backoff if the body indicates throttling or a 5xx server error.

Example fix

// before
const models = await kiro.listAvailableModels(staleToken, profileArn);
// after
const fresh = await refreshTokenIfNeeded(staleToken);
const models = await kiro.listAvailableModels(fresh, profileArn);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!accessToken || typeof accessToken !== "string") {
  throw new Error("A valid access token is required before listing models");
}
if (!profileArn) {
  profileArn = await kiro.resolveProfileArn(accessToken); // obtain if unknown
}

Type guard

function hasValidCredentials(cred) {
  return typeof cred?.accessToken === "string" && cred.accessToken.length > 0 &&
    (cred.profileArn == null || typeof cred.profileArn === "string");
}

Try / catch

try {
  const models = await kiro.listAvailableModels(token, profileArn);
} catch (e) {
  if (e.message.startsWith("Failed to list models:")) {
    if (/AccessDenied|Unauthorized|expired/i.test(e.message)) {
      // refresh token / re-run OAuth, then retry once
    } else if (/Throttl|ServiceUnavailable|5\d\d/.test(e.message)) {
      // retry with exponential backoff
    }
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling listAvailableModels(accessToken, profileArn) where the POST to https://codewhisperer.us-east-1.amazonaws.com returns response.ok === false — expired/invalid access token, missing or wrong profileArn, insufficient permissions, or endpoint unavailability (5xx).

Common situations: OAuth access token expired and was not refreshed; profileArn omitted, null, or belonging to a different region/account; token from a different auth method being used against CodeWhisperer; AWS-side outage or throttling.

Related errors


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