{"record":{"id":"1d16bbafeea33f04","repo":"janhq/jan","slug":"provider-must-have-base-url-configured-1d16bb","errorCode":null,"errorMessage":"Provider must have base_url configured","messagePattern":"Provider must have base_url configured","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/services/providers/tauri.ts","lineNumber":149,"sourceCode":"\n      return runtimeProviders.concat(builtinProviders as ModelProvider[])\n    } catch (error: unknown) {\n      console.error('Error getting providers in Tauri:', error)\n      return []\n    }\n  }\n\n  async deleteProviderKeys(providerName: string): Promise<void> {\n    try {\n      await invoke('delete_provider_keys', { provider: providerName })\n    } catch (error) {\n      console.error(`Failed to delete keyring keys for ${providerName}:`, error)\n    }\n  }\n\n  async fetchModelsFromProvider(provider: ModelProvider): Promise<string[]> {\n    if (!provider.base_url) {\n      throw new Error('Provider must have base_url configured')\n    }\n\n    try {\n      const keyChain = providerRemoteApiKeyChain(provider)\n      const keyAttempts: (string | undefined)[] =\n        keyChain.length > 0 ? keyChain : [undefined]\n\n      let lastStatus = 0\n      let lastStatusText = ''\n\n      for (let ki = 0; ki < keyAttempts.length; ki++) {\n        const key = keyAttempts[ki]\n        const headers: Record<string, string> = {\n          'Content-Type': 'application/json',\n        }\n\n        if (\n          provider.base_url.includes('localhost:') ||","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/services/providers/tauri.ts#L131-L167","documentation":"Thrown by TauriProviderService.fetchModelsFromProvider (providers/tauri.ts:149) when the provider object has no base_url. The method needs base_url to build the `${base_url}/models` GET request via fetchTauri. Identical message to catalog error [147] but on the provider-service code path used to populate the model list in Settings.","triggerScenarios":"fetchModelsFromProvider is called for a provider with base_url === undefined/null/''. Common when a custom OpenAI-compatible provider was saved without an endpoint, or the field was cleared.","commonSituations":"Custom provider created with only an API key; base_url cleared by the user but provider retained; config deserialized from an older schema without base_url; user expects the provider's default endpoint to be inferred but it is not.","solutions":["Open Settings > Model Providers and set the base URL for the provider (e.g. https://api.openai.com/v1).","Validate base_url in the provider form before allowing 'fetch models'.","Pre-fill known providers' base URLs from a defaults table on creation."],"exampleFix":"// before\nif (!provider.base_url) {\n  throw new Error('Provider must have base_url configured')\n}\n// after: guard at the UI; disable the 'Fetch Models' button\nconst canFetch = Boolean(provider.base_url?.trim())\n// <Button disabled={!canFetch} onClick={() => fetchModelsFromProvider(provider)}>Fetch Models</Button>","handlingStrategy":"validation","validationCode":"function hasBaseUrl(p: ModelProvider): boolean {\n  return typeof p.base_url === 'string' && p.base_url.trim().length > 0\n}\n// before fetchModelsFromProvider:\nif (!hasBaseUrl(provider)) {\n  throw new Error('Set a base URL for this provider in Settings.')\n}","typeGuard":"function providerHasBaseUrl(p: unknown): p is ModelProvider & { base_url: string } {\n  return typeof p === 'object' && p !== null && typeof (p as ModelProvider).base_url === 'string' && (p as ModelProvider).base_url!.trim().length > 0\n}","tryCatchPattern":"try {\n  return await providerService.fetchModelsFromProvider(provider)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Provider must have base_url configured') {\n    promptForBaseUrl(provider.provider)\n    return []\n  }\n  throw e\n}","preventionTips":["Require base_url in the provider form before save.","Disable the 'Fetch Models' button when base_url is empty.","Pre-fill known providers' base URLs from a defaults table.","Normalize base_url (trim, strip trailing slash) on save."],"tags":["provider","configuration","base-url","validation","tauri","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}