mastra-ai/mastra · error

models.dev returned ${response.status}

Error message

models.dev returned ${response.status}

What it means

fetchBedrockModels queries the models.dev API to enumerate available Amazon Bedrock models. When the HTTP response status is not ok (4xx/5xx), the function throws this generic error embedding the numeric status. It is a fail-fast guard against parsing garbage from a failed catalog request.

Source

Thrown at mastracode/sdk/src/providers/amazon-bedrock.ts:52

interface CatalogCacheEntry {
  fetchedAt: number;
  ttl: number;
  models: BedrockModelEntry[];
}

let catalogCache: CatalogCacheEntry | null = null;
let inflightFetch: Promise<BedrockModelEntry[]> | null = null;

/** Reset the in-process Bedrock catalog cache (test seam). */
export function clearBedrockCatalogCache(): void {
  catalogCache = null;
  inflightFetch = null;
}

async function fetchBedrockModels(signal: AbortSignal): Promise<BedrockModelEntry[]> {
  const response = await fetch(MODELS_DEV_API_URL, { signal });
  if (!response.ok) {
    throw new Error(`models.dev returned ${response.status}`);
  }
  const data = (await response.json()) as Record<string, { models?: Record<string, unknown> }>;
  const provider = data[BEDROCK_PROVIDER_ID];
  const models = provider?.models ?? {};
  return Object.keys(models)
    .sort()
    .map(id => ({ id }));
}

/**
 * Return the available Amazon Bedrock models.
 *
 * - Returns the cached list when a recent fetch succeeded.
 * - On cache miss / expiry, fetches the models.dev catalog with a 5s timeout and
 *   caches it for an hour.
 * - On fetch failure, returns a small hard-coded fallback (so packs still work
 *   offline) and caches that briefly to avoid hammering the network.
 *

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check network connectivity and retry, since 5xx/429 are usually transient
  2. Inspect the status code in the message: 403/401 means a proxy or firewall is intercepting the request
  3. Verify MODELS_DEV_API_URL is reachable (curl it directly) and the API has not moved
  4. Pin a fallback/offline model list or cache the last successful response for offline use

Example fix

// before
const models = await sdk.models();
// after
let models;
try {
  models = await sdk.models();
} catch (err) {
  if ((err as Error).message.startsWith('models.dev returned')) {
    models = FALLBACK_BEDROCK_MODELS; // cached/known list
  } else throw err;
}
Defensive patterns

Strategy: fallback

Validate before calling

const res = await fetch(MODELS_DEV_API_URL);
if (!res.ok) throw new Error(`models.dev unreachable: ${res.status}`);

Type guard

null

Try / catch

try {
  models = await sdk.models();
} catch (err) {
  if (err instanceof Error && /models\.dev returned \d+/.test(err.message)) {
    models = CACHED_MODELS; // or rethrow with context
  } else throw err;
}

Prevention

When it happens

Trigger: Calling `models` (which calls fetchBedrockModels) when the models.dev endpoint returns a non-2xx status: 404 (API path changed), 429 (rate limited), 5xx (service outage), or a proxy/firewall blocking the request.

Common situations: Corporate proxies or firewalls returning 403/502 for external APIs; models.dev being temporarily down or rate-limiting; offline or air-gapped environments where a captive portal returns an HTML error page with 4xx/5xx; DNS hijacking to an error page.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/d2aeea3a55663d30. Report an issue: GitHub.