can1357/oh-my-pi · error

HTTP ${res.status} from ${modelsUrl}

Error message

HTTP ${res.status} from ${modelsUrl}

What it means

discoverOpenAIModelsList fetches `GET <baseUrl>/models` from an OpenAI-compatible endpoint (including LM Studio) to enumerate models. Any non-ok HTTP status throws `Error("HTTP <status> from <modelsUrl>")`. The default timeout is 10s (overridable via discovery.timeoutMs) and a Bearer key from the provider's resolver is attached when available.

Source

Thrown at packages/coding-agent/src/config/model-discovery.ts:831

	const baseHeaders: Record<string, string> = { ...(providerConfig.headers ?? {}) };
	let headers = baseHeaders;
	const timeoutMs = providerConfig.discovery.timeoutMs ?? 10_000;
	const attempt = async (h: Record<string, string>) => {
		const nativeMetadataPromise =
			providerConfig.discovery.type === "lm-studio"
				? withTimeoutSignal(timeoutMs, signal =>
						fetchLmStudioNativeModelMetadata(baseUrl, ctx.fetch, { headers: h, signal }),
					)
				: Promise.resolve(null);
		const [payload, nativeMetadata] = await Promise.all([
			withTimeoutSignal(timeoutMs, async signal => {
				const res = await ctx.fetch(modelsUrl, {
					headers: h,
					signal,
				});
				if (!res.ok) {
					throw new Error(`HTTP ${res.status} from ${modelsUrl}`);
				}
				headers = h;
				return (await res.json()) as {
					data?: Array<{
						id?: string;
						max_model_len?: unknown;
						context_length?: unknown;
						input?: unknown;
						input_modalities?: unknown;
						architecture?: unknown;
					}>;
				};
			}),
			nativeMetadataPromise,
		]);
		return [payload, nativeMetadata] as const;
	};
	const apiKey = await ctx.getBearerApiKeyResolver(providerConfig.provider);

View on GitHub (pinned to 9690622007)

Solutions

  1. Test `curl -H "Authorization: Bearer <key>" <baseUrl>/models` and match the reported status to fix auth (401/403) or the URL (404).
  2. Set/correct apiKey in the provider config so the Bearer attempt carries a valid credential.
  3. Fix baseUrl to end at the right prefix (usually include /v1 for OpenAI-compatible servers).
  4. If 429/5xx, back off and retry or raise discovery.timeoutMs; check the upstream server/proxy logs.

Example fix

// before: 404 because /v1 missing
{ "baseUrl": "https://gw.example.com", "discovery": { "type": "models-list" } }
// after
{ "baseUrl": "https://gw.example.com/v1", "apiKey": "sk-...", "discovery": { "type": "models-list" } }
Defensive patterns

Strategy: validation

Validate before calling

const res = await fetch(`${baseUrl.replace(/\/$/, '')}/models`, { headers: { Authorization: `Bearer ${apiKey}` } });
if (res.status === 401 || res.status === 403) throw new Error("models-list discovery: invalid or missing API key");
if (res.status === 404) throw new Error("models-list discovery: check baseUrl includes /v1 and the server exposes /models");

Type guard

null

Try / catch

try {
  const models = await discoverOpenAIModelsList(cfg, ctx);
} catch (err) {
  const status = (err as any)?.message?.match?.(/^HTTP (\d+)/)?.[1];
  if (status === "401" || status === "403") {
    logger.warn("Discovery auth failed; check apiKey", { baseUrl: cfg.baseUrl });
  }
  return bundledModelFallback(cfg.provider);
}

Prevention

When it happens

Trigger: discoverOpenAIModelsList called (via discoverModelsByProviderType) when the /models endpoint returns 401 (missing/invalid API key), 403 (key lacks list permission), 404 (baseUrl wrong, /v1 missing or duplicated), 429 (rate limit), or 5xx from the upstream server/proxy.

Common situations: Expired or wrong API key against a hosted OpenAI-compatible gateway; LM Studio server not started (connection refused shows differently, but a proxy in front yields 502); baseUrl missing the /v1 segment for strict OpenAI-compatible servers; self-hosted vLLM/TGI returning 404 because models route is disabled.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/1f4425001f61658e. Report an issue: GitHub.