{"record":{"id":"b2e13f6b18aae382","repo":"janhq/jan","slug":"cannot-connect-to-provider-provider-at-provid","errorCode":null,"errorMessage":"Cannot connect to ${provider.provider} at ${provider.base_url}. Please check that the service is running and accessible.","messagePattern":"Cannot connect to (.+?) at (.+?)\\. Please check that the service is running and accessible\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/services/providers/tauri.ts","lineNumber":272,"sourceCode":"      const structuredErrorPrefixes = [\n        'Authentication failed',\n        'Access forbidden',\n        'Models endpoint not found',\n        'Failed to fetch models from',\n      ]\n\n      if (\n        error instanceof Error &&\n        structuredErrorPrefixes.some((prefix) =>\n          (error as Error).message.startsWith(prefix)\n        )\n      ) {\n        throw new Error(error.message)\n      }\n\n      // Provide helpful error message for any connection errors\n      if (error instanceof Error && error.message.includes('fetch')) {\n        throw new Error(\n          `Cannot connect to ${provider.provider} at ${provider.base_url}. Please check that the service is running and accessible.`\n        )\n      }\n\n      // Generic fallback\n      throw new Error(\n        `Unexpected error while fetching models from ${provider.provider}: ${error instanceof Error ? error.message : 'Unknown error'}`\n      )\n    }\n  }\n\n  async updateSettings(\n    providerName: string,\n    settings: ProviderSetting[]\n  ): Promise<void> {\n    try {\n      // API keys are persisted to the OS keyring only (via\n      // register_provider_config), never to the extension's settings.json.","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/services/providers/tauri.ts#L254-L290","documentation":"Thrown when getModels catches an error whose message contains the substring 'fetch' - the signature of a network-level failure from fetchTauri (TypeError: Failed to fetch, DNS failure, connection refused, TLS error, CORS rejection). It reformulates the low-level network error into an actionable message naming the provider and base_url.","triggerScenarios":"fetchTauri rejects with a TypeError such as 'Failed to fetch' - provider host unreachable, wrong base_url scheme/host/port, CORS preflight failure, TLS certificate error, or a localhost service that is not running.","commonSituations":"User configured a local provider (llama.cpp / Ollama) but it is not running; base_url typo; HTTPS endpoint with a self-signed cert; CORS blocking the request from the Tauri webview; the localhost Origin-header injection (tauri://localhost) did not apply because the host string did not match 'localhost:' or '127.0.0.1:'.","solutions":["Confirm the service is running: curl -i ${base_url}/models from a terminal.","Verify base_url exactly - scheme (http/https), host, port, and no trailing slash / path mismatches.","For localhost providers, confirm the Origin header logic applies; it only triggers for hosts containing 'localhost:' or '127.0.0.1:'.","For self-signed certs, trust the cert or use http locally; check the provider's CORS configuration."],"exampleFix":"// before: localhost provider not started -> 'Cannot connect to llama.cpp at http://127.0.0.1:8080...'\n// after: validate reachability when saving provider settings\nasync function pingProvider(base_url: string, key?: string): Promise<boolean> {\n  const headers: Record<string,string> = {}\n  if (key) { headers['x-api-key'] = key; headers['Authorization'] = `Bearer ${key}` }\n  try { return (await fetch(`${base_url}/models`, { headers })).ok } catch { return false }\n}","handlingStrategy":"retry","validationCode":"async function canReach(base_url: string): Promise<boolean> {\n  try {\n    await fetch(`${base_url}/models`, { method: 'GET', mode: 'no-cors' })\n    return true\n  } catch { return false }\n}","typeGuard":"function isConnectionError(e: unknown): boolean {\n  return e instanceof Error && /fetch|network|ECONNREFUSED|ENOTFOUND|certificate|CORS/i.test(e.message)\n}","tryCatchPattern":"try {\n  await provider.getModels(p)\n} catch (e) {\n  if (isConnectionError(e)) {\n    showRetryableError(`Cannot reach ${p.base_url}`, { retry: () => provider.getModels(p) })\n  } else throw e\n}","preventionTips":["Run a connectivity test when saving provider settings.","Offer a retry button for connection errors.","Surface base_url prominently so users can spot typos."],"tags":["network","connection","cors","provider-api","base-url"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}