decolua/9router · error

API key is required

Error message

API key is required

What it means

validateApiKey is a synchronous guard: before making any network call it requires a non-empty, non-whitespace string apiKey. If apiKey is undefined, null, not a string, or only whitespace, it throws 'API key is required' immediately. This is a fail-fast precondition so an obviously invalid credential never reaches the Amazon Q endpoint.

Source

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

      const error = await response.text();
      throw new Error(`Failed to list API-key models: ${error}`);
    }

    const data = await response.json();
    const models = Array.isArray(data?.models) ? data.models : [];
    if (models.length === 0) {
      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",
    };
  }

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Pass the API key string as the first argument, e.g. validateApiKey(process.env.KIRO_API_KEY).
  2. Check the credential source: confirm the env var / config field is set and correctly named before calling.
  3. Trim the value in your own code and reject empty strings early with a clearer app-level message.
  4. If passing from a credentials object, use the right property: cred.apiKey, not cred.

Example fix

// before
await kiro.validateApiKey(config.kiro_key); // field name typo -> undefined
// after
if (!process.env.KIRO_API_KEY) throw new Error("Set KIRO_API_KEY first");
await kiro.validateApiKey(process.env.KIRO_API_KEY);
Defensive patterns

Strategy: validation

Validate before calling

function requireApiKey(key) {
  if (!key || typeof key !== "string" || !key.trim()) {
    throw new Error("Kiro API key is missing or empty");
  }
  return key.trim();
}
await kiro.validateApiKey(requireApiKey(process.env.KIRO_API_KEY));

Type guard

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

Prevention

When it happens

Trigger: Calling kiroService.validateApiKey(undefined), validateApiKey(null), validateApiKey(42), validateApiKey(" "), or validateApiKey("") — i.e. any call where the first argument fails `apiKey && typeof apiKey === 'string' && apiKey.trim()`.

Common situations: Reading the key from an unset env var (process.env.KIRO_API_KEY === undefined); a config object whose key field is misspelled (apiKey vs api_key); trimming stripping a whitespace-only placeholder; passing a credentials object instead of the string itself.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


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