{"record":{"id":"fb23763fa5daa8fb","repo":"decolua/9router","slug":"api-key-returned-no-available-models","errorCode":null,"errorMessage":"API key returned no available models","messagePattern":"API key returned no available models","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/kiro.js","lineNumber":322,"sourceCode":"      method: \"GET\",\n      headers: {\n        \"Authorization\": `Bearer ${apiKey}`,\n        \"TokenType\": \"API_KEY\",\n        \"Accept\": \"application/json\",\n        \"User-Agent\": \"AWS-SDK-JS/3.0.0 kiro-ide/1.0.0\",\n        \"X-Amz-User-Agent\": \"aws-sdk-js/3.0.0 kiro-ide/1.0.0\",\n      },\n    });\n\n    if (!response.ok) {\n      const error = await response.text();\n      throw new Error(`Failed to list API-key models: ${error}`);\n    }\n\n    const data = await response.json();\n    const models = Array.isArray(data?.models) ? data.models : [];\n    if (models.length === 0) {\n      throw new Error(\"API key returned no available models\");\n    }\n    return models;\n  }\n\n  /**\n   * Validate an API-key credential through the same Amazon Q surface used for\n   * inference. API keys are account-bound but do not require a profileArn.\n   */\n  async validateApiKey(apiKey, region = \"us-east-1\") {\n    if (!apiKey || typeof apiKey !== \"string\" || !apiKey.trim()) {\n      throw new Error(\"API key is required\");\n    }\n    const trimmed = apiKey.trim();\n\n    try {\n      await this.listAvailableApiKeyModels(trimmed, region);\n    } catch (error) {\n      throw new Error(`API key validation failed: ${error.message}`);","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/kiro.js#L304-L340","documentation":"KiroService.listAvailableApiKeyModels calls Amazon Q's ListAvailableModels endpoint with the user-supplied API key as a Bearer token (TokenType: API_KEY). If the endpoint returns HTTP 200 but the response body contains an empty `models` array, the key is not actually able to run inference (a bearer-only ListAvailableProfiles call can return 200 with an empty list for an arbitrary key), so the service throws this error to signal the key is unusable. It is a validation verdict, not a network failure.","triggerScenarios":"Calling listAvailableApiKeyModels(apiKey, region) (directly or via validateApiKey) where GET https://q.<region>.amazonaws.com/ListAvailableModels?origin=AI_EDITOR succeeds with HTTP 200 but data.models is missing, null, or an empty array.","commonSituations":"Pasting an API key from the wrong AWS account/organization that has no Amazon Q / Kiro model subscriptions; a region that is valid but has no models enabled for the account; a revoked or malformed-but-accepted key; the upstream contract changed and `models` moved/renamed in the response so the parser sees an empty list.","solutions":["Verify the API key belongs to an account with Amazon Q / Kiro (AI_EDITOR) model access; re-copy the key from the Kiro dashboard.","Retry with a different valid AWS region argument (e.g. us-east-1), since the model catalog is queried per-region.","Check upstream response shape: inspect the raw ListAvailableModels JSON to confirm `models` exists and is non-empty (a renamed field makes a valid key look empty).","If validateApiKey wrapped this, read error.message for the root cause since it rethrows as 'API key validation failed: ...'."],"exampleFix":"// before\nconst models = await kiro.listAvailableApiKeyModels(apiKey, \"eu-central-1\");\n// after\nconst models = await kiro.listAvailableApiKeyModels(apiKey, \"us-east-1\"); // region with models enabled","handlingStrategy":"validation","validationCode":"function looksLikeKiroApiKey(key) {\n  return typeof key === \"string\" && key.trim().length > 0;\n}\n// Note: emptiness cannot be pre-checked for model access; catch the specific error instead:\ntry {\n  await kiro.listAvailableApiKeyModels(key, region);\n} catch (e) {\n  if (e.message === \"API key returned no available models\") {\n    // key authenticates but has no model access — wrong account/region\n  }\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  const models = await kiro.listAvailableApiKeyModels(key, region);\n} catch (e) {\n  if (e.message === \"API key returned no available models\") {\n    // treat key as valid-format but unauthorized: prompt for another key or region\n  } else {\n    throw e; // network / HTTP errors\n  }\n}","preventionTips":["Use keys from an account with an active Amazon Q / Kiro (AI_EDITOR) subscription.","Default to us-east-1 unless you know models are enabled in another region.","Test new keys with a single validation call before persisting them.","Watch for upstream schema changes to the `models` field when upgrading."],"tags":["oauth","api-key","kiro","aws","empty-response"],"backgroundTag":"api-key-no-models","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}