{"record":{"id":"7c0b07109560f6b6","repo":"GitbookIO/gitbook","slug":"failed-to-fetch-search-index-response-status","errorCode":null,"errorMessage":"Failed to fetch search index: ${response.status}","messagePattern":"Failed to fetch search index: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/gitbook/src/components/Search/site-index.ts","lineNumber":68,"sourceCode":"    indexURL: string\n): Promise<{ version: 1; pages: SiteIndexPage[] }> {\n    return JSON.parse(await fetchSiteIndexText(indexURL));\n}\n\n/**\n * Drop the cached raw text (several MB for large sites) once a consumer has\n * turned it into a longer-lived form. Purely a memory release: a later consumer\n * re-fetches, hitting the HTTP cache.\n */\nexport function releaseSiteIndex(): void {\n    siteIndexText = null;\n}\n\nfunction fetchSiteIndexText(indexURL: string): Promise<string> {\n    if (!siteIndexText) {\n        siteIndexText = fetch(indexURL).then((response) => {\n            if (!response.ok) {\n                throw new Error(`Failed to fetch search index: ${response.status}`);\n            }\n            return response.text();\n        });\n\n        siteIndexText.catch(() => {\n            siteIndexText = null;\n        });\n    }\n\n    return siteIndexText;\n}\n","sourceCodeStart":50,"sourceCodeEnd":80,"githubUrl":"https://github.com/GitbookIO/gitbook/blob/db67585ee243d063c459a855988f21612cea9c95/packages/gitbook/src/components/Search/site-index.ts#L50-L80","documentation":"Thrown by fetchSiteIndexText in the GitBook search client when the HTTP request for the site's prebuilt search index returns a non-OK status. The function fetches indexURL, checks response.ok, and throws with the failing status code; the promise is memoized in siteIndexText and reset to null on failure so a later call retries the fetch.","triggerScenarios":"GET of the site index URL returning 404 (index not generated/deployed for the site), 401/403 (private site with bad auth), 500 (server error building the index), or any non-2xx; a CDN or middleware blocking the request; an incorrect indexURL passed to fetchSiteIndex/prefetchSiteIndex.","commonSituations":"Site deployed without a search index artifact (new sites, build config change); URL rewriting/proxying in local dev (the dev server proxy) mangling the index path; authentication/cookie issues on private spaces; host returning an HTML error page with status 404/500.","solutions":["Open the indexURL directly in a browser/curl to see the actual status and body (often 404 vs 403 tells the story).","If 404: verify the site publishes a search index and that the URL/version segment is correct and current.","If 401/403: ensure the request carries the visitor's auth cookies/headers for private sites.","Rely on the built-in memoization reset: the failed promise is cleared, so calling fetchSiteIndex again after fixing the underlying issue retries rather than serving a rejected promise."],"exampleFix":"// before\nconst index = await fetchSiteIndex(indexURL);\n\n// after\nconst index = await fetchSiteIndex(indexURL).catch((error) => {\n    if (String(error.message).startsWith('Failed to fetch search index:')) {\n        return null; // fall back to non-index (slower) search or hide search UI\n    }\n    throw error;\n});","handlingStrategy":"retry","validationCode":"// Optional preflight (cheap HEAD) before the real fetch:\nconst ok = await fetch(indexURL, { method: 'HEAD' }).then((r) => r.ok).catch(() => false);\nif (!ok) {\n    fallbackToServerSearch();\n}","typeGuard":"const isSearchIndexAvailable = async (url: string): Promise<boolean> => {\n    try {\n        const res = await fetch(url, { method: 'HEAD' });\n        return res.ok;\n    } catch {\n        return false;\n    }\n};","tryCatchPattern":"try {\n    const index = await fetchSiteIndex(indexURL);\n} catch (error) {\n    if (error instanceof Error && error.message.startsWith('Failed to fetch search index:')) {\n        return fallbackSearch();\n    }\n    throw error;\n}","preventionTips":["The module already resets its memoized promise on failure — retrying later is safe and expected.","Verify the index URL is part of your deployment artifacts (404 is the most common cause).","Include auth cookies for private sites when fetching the index.","Log the status code embedded in the message to classify 404 vs 401 vs 5xx quickly."],"tags":["search","http","network","index","gitbook"],"backgroundTag":"http-request-failed","analyzedSha":"db67585ee243d063c459a855988f21612cea9c95","analyzedAt":"2026-08-28T17:49:47.831Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}