janhq/jan · error · Error

Provider must have base_url configured

Error message

Provider must have base_url configured

What it means

Thrown by fetchTopRemoteModels (remoteModelCatalog.ts:205) when a remote catalog provider object has no base_url. The function needs base_url to construct the `${base_url}/models` GET request and refuses to proceed without it. Distinct from the identical-message error in providers/tauri.ts:149 which is a different code path.

Source

Thrown at web-app/src/lib/remoteModelCatalog.ts:205

  }
  return {
    ok: response.ok,
    status: response.status,
    statusText: response.statusText,
    body,
  }
}

export async function fetchTopRemoteModels(
  provider: ProviderLike,
  fetchImpl: FetchImpl
): Promise<RemoteCatalogModel[]> {
  const kind = resolveCatalogKind(provider)
  if (!kind) {
    throw new Error(`Catalog not supported for ${provider.provider}`)
  }
  if (!provider.base_url) {
    throw new Error('Provider must have base_url configured')
  }

  const keyChain = providerRemoteApiKeyChain(provider)
  const attempts: (string | undefined)[] = keyChain.length > 0 ? keyChain : [undefined]

  let lastStatus = 0
  let lastStatusText = ''
  for (let i = 0; i < attempts.length; i++) {
    const result = await getJson(
      fetchImpl,
      `${provider.base_url}/models`,
      buildHeaders(provider, attempts[i])
    )
    lastStatus = result.status
    lastStatusText = result.statusText
    if (!result.ok) {
      if ([401, 403, 429].includes(result.status) && i < attempts.length - 1) continue
      throw new Error(`Failed to fetch models from ${provider.provider}: ${result.status} ${result.statusText}`)

View on GitHub (pinned to fad3f12a14)

Solutions

  1. In Settings > Model Providers, set the provider's base URL (e.g. https://api.openai.com/v1).
  2. Validate provider.base_url in the provider-edit form before saving so the catalog call cannot be reached without it.
  3. If the provider is local (no public endpoint), do not offer the 'browse remote models' action for it.

Example fix

// before
if (!provider.base_url) {
  throw new Error('Provider must have base_url configured')
}
// after: guard at the caller, never reach fetchTopRemoteModels
if (!provider.base_url?.trim()) {
  return { models: [], error: 'missing_base_url' }
}
Defensive patterns

Strategy: validation

Validate before calling

function hasBaseUrl(p: ProviderLike): boolean {
  return typeof p.base_url === 'string' && p.base_url.trim().length > 0
}
// before fetchTopRemoteModels:
if (!hasBaseUrl(provider)) {
  return { models: [], error: 'missing_base_url' }
}

Type guard

function providerHasBaseUrl(p: unknown): p is ProviderLike & { base_url: string } {
  return typeof p === 'object' && p !== null && typeof (p as ProviderLike).base_url === 'string' && (p as ProviderLike).base_url!.trim().length > 0
}

Try / catch

try {
  return await fetchTopRemoteModels(provider, fetchImpl)
} catch (e) {
  if (e instanceof Error && e.message === 'Provider must have base_url configured') {
    promptForBaseUrl(provider.provider)
    return []
  }
  throw e
}

Prevention

When it happens

Trigger: A provider passed to fetchTopRemoteModels has base_url === undefined, null, or '' (empty string). The catalog kind check already passed, so this is a partially-configured provider that has a known flavor but no endpoint.

Common situations: Custom provider created with only an API key and no endpoint; base_url field cleared by the user but provider not deleted; provider object deserialized from old config that predates the base_url field.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/83916f91595747cd. Report an issue: GitHub.