decolua/9router · error

API key validation failed: ${error.message}

Error message

API key validation failed: ${error.message}

What it means

validateApiKey delegates the actual check to listAvailableApiKeyModels and wraps any failure with 'API key validation failed: <root message>'. This wrapper preserves the root cause in error.message while giving callers a single, predictable error for the whole API-key validation flow. The original failure can be a network error, a non-OK HTTP response ('Failed to list API-key models: ...'), or the empty-models verdict.

Source

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

      throw new Error("API key returned no available models");
    }
    return models;
  }

  /**
   * Validate an API-key credential through the same Amazon Q surface used for
   * inference. API keys are account-bound but do not require a profileArn.
   */
  async validateApiKey(apiKey, region = "us-east-1") {
    if (!apiKey || typeof apiKey !== "string" || !apiKey.trim()) {
      throw new Error("API key is required");
    }
    const trimmed = apiKey.trim();

    try {
      await this.listAvailableApiKeyModels(trimmed, region);
    } catch (error) {
      throw new Error(`API key validation failed: ${error.message}`);
    }

    return {
      accessToken: trimmed,
      refreshToken: null,
      profileArn: null,
      region,
      authMethod: "api_key",
    };
  }

  /**
   * List available models from CodeWhisperer API
   */
  async listAvailableModels(accessToken, profileArn) {
    const endpoint = "https://codewhisperer.us-east-1.amazonaws.com";
    const target = "AmazonCodeWhispererService.ListAvailableModels";

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Parse the wrapped root cause from error.message after 'API key validation failed: ' and act on it (401/403 -> new key, network -> connectivity, empty models -> account/region access).
  2. Regenerate the Kiro API key if the message contains an auth/forbidden response body.
  3. Verify the region argument is a valid AWS region reachable from your network.
  4. Add your own try/catch if you need the original error object, since the wrapper discards it.

Example fix

// before
await kiro.validateApiKey(key); // throws 'API key validation failed: ...'
// after
try {
  await kiro.validateApiKey(key);
} catch (e) {
  const root = e.message.replace("API key validation failed: ", "");
  if (/40[13]/.test(root)) console.error("Key rejected — regenerate it");
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const key = (cred?.apiKey ?? "").trim();
if (!key) throw new Error("Provide a Kiro API key before validation");

Type guard

function isNonEmptyString(v) {
  return typeof v === "string" && v.trim().length > 0;
}

Try / catch

try {
  await kiro.validateApiKey(key, "us-east-1");
} catch (e) {
  const root = e.message.startsWith("API key validation failed: ")
    ? e.message.slice("API key validation failed: ".length)
    : e.message;
  if (/no available models/.test(root)) { /* account/region access issue */ }
  else if (/Failed to list API-key models/.test(root)) { /* HTTP-level: auth or network */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling validateApiKey(apiKey, region) where listAvailableApiKeyModels throws for any reason: fetch rejects (DNS/network), Amazon Q returns non-200 (invalid key -> 401/403, bad region -> 400), or the 200 response has an empty models array.

Common situations: Expired or revoked Kiro API key (403 in the wrapped message); typo in region causing an invalid endpoint; offline environment or proxy blocking q.<region>.amazonaws.com; account without model access (empty models message wrapped here).

Related errors


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