{"record":{"id":"9b4399545ba4df1b","repo":"janhq/jan","slug":"failed-to-fetch-huggingface-repository-response","errorCode":null,"errorMessage":"Failed to fetch HuggingFace repository: ${response.status} ${response.statusText}","messagePattern":"Failed to fetch HuggingFace repository: (.+?) (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"web-app/src/services/models/default.ts","lineNumber":121,"sourceCode":"        return null\n      }\n\n      const response = await fetch(\n        `https://huggingface.co/api/models/${cleanRepoId}?blobs=true&files_metadata=true`,\n        {\n          headers: hfToken\n            ? {\n                Authorization: `Bearer ${hfToken}`,\n              }\n            : {},\n        }\n      )\n\n      if (!response.ok) {\n        if (response.status === 404) {\n          return null // Repository not found\n        }\n        throw new Error(\n          `Failed to fetch HuggingFace repository: ${response.status} ${response.statusText}`\n        )\n      }\n\n      const repoData = await response.json()\n      return repoData\n    } catch (error) {\n      console.error('Error fetching HuggingFace repository:', error)\n      return null\n    }\n  }\n\n  convertHfRepoToCatalogModel(repo: HuggingFaceRepo): CatalogModel {\n    // Format file size helper\n    const formatFileSize = (size?: number) => {\n      if (!size) return 'Unknown size'\n      if (size < 1024 ** 3) return `${(size / 1024 ** 2).toFixed(1)} MB`\n      return `${(size / 1024 ** 3).toFixed(1)} GB`","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/janhq/jan/blob/fad3f12a147d138388a66f0d92a02b2675f65294/web-app/src/services/models/default.ts#L103-L139","documentation":"Thrown by ModelService.fetchHuggingFaceRepo (default.ts:121) when the HuggingFace API response is non-OK and not 404. (404 is handled above by returning null.) Embeds response.status and statusText. The surrounding catch swallows the error and returns null, so callers see null rather than the throw — the throw mainly distinguishes 404 (legit 'not found') from other failures in logs.","triggerScenarios":"GET https://huggingface.co/api/models/{repoId}?blobs=true&files_metadata=true returns 401/403 (private repo, token invalid/missing), 429 (rate-limited), or 5xx (HuggingFace incident). 404 is intentionally converted to null before this throw.","commonSituations":"User pasted a private repo id without setting a HuggingFace token (401/403); HuggingFace rate-limits unauthenticated requests (429); the hfToken passed is expired; transient HuggingFace outage (5xx).","solutions":["For private repos, set a valid HuggingFace access token in settings so the Authorization: Bearer header is sent.","For 429, slow down repo lookups or authenticate to raise the rate limit.","For 5xx, retry — HuggingFace incidents are usually short.","Treat null return as 'not found or unavailable' and prompt the user to verify the repo id."],"exampleFix":"// before\nif (!response.ok) {\n  if (response.status === 404) return null\n  throw new Error(`Failed to fetch HuggingFace repository: ${response.status} ${response.statusText}`)\n}\n// after: surface auth/rate-limit distinctly before swallowing to null\nif (!response.ok) {\n  if (response.status === 404) return null\n  if (response.status === 401 || response.status === 403) {\n    console.warn('HuggingFace auth failed — set a token in Settings for private repos')\n  }\n  throw new Error(`Failed to fetch HuggingFace repository: ${response.status} ${response.statusText}`)\n}","handlingStrategy":"fallback","validationCode":"function looksLikePrivateRepo(repoId: string, hasToken: boolean): boolean {\n  return Boolean(repoId) && !hasToken && repoId.split('/')[0] !== defaultPublicNamespace\n}\n// before fetchHuggingFaceRepo, prompt for a token when a private repo is suspected.","typeGuard":"function isHfRepo(x: unknown): x is HuggingFaceRepo {\n  return typeof x === 'object' && x !== null && 'siblings' in x\n}","tryCatchPattern":"try {\n  return await this.fetchHuggingFaceRepo(repoId, hfToken)\n} catch (e) {\n  console.error('HF repo lookup failed', e)\n  return null  // match the function's existing null-on-failure contract\n}","preventionTips":["Prompt for a HuggingFace token before looking up likely-private repos.","Treat 401/403 as 'token missing/invalid' and 429 as 'rate-limited' in user messaging.","Cache repo lookups to avoid repeated HF API hits.","Validate repoId format (owner/name) before the network call."],"tags":["huggingface","network","http-status","auth","fetch","typescript"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}