{"record":{"id":"5e57b041ff59210e","repo":"withastro/astro","slug":"your-project-uses-feature-but-your-custom-src","errorCode":null,"errorMessage":"Your project uses ${feature}, but your custom src/fetch.ts does not call the ${feature}() handler. This feature will not work unless your fetch handler calls it.","messagePattern":"Your project uses (.+?), but your custom src/fetch\\.ts does not call the (.+?)\\(\\) handler\\. This feature will not work unless your fetch handler calls it\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/astro/src/core/app/base.ts","lineNumber":520,"sourceCode":"\t\t}\n\t\tif (manifest.sessionConfig && !(used & FetchFeatures.sessions)) {\n\t\t\tmissing.push('sessions');\n\t\t}\n\t\tif (manifest.actions && !(used & FetchFeatures.actions)) {\n\t\t\tmissing.push('actions');\n\t\t}\n\t\tif (manifest.middleware && !(used & FetchFeatures.middleware)) {\n\t\t\tmissing.push('middleware');\n\t\t}\n\t\tif (manifest.i18n && manifest.i18n.strategy !== 'manual' && !(used & FetchFeatures.i18n)) {\n\t\t\tmissing.push('i18n');\n\t\t}\n\t\tif (manifest.cacheConfig && !(used & FetchFeatures.cache)) {\n\t\t\tmissing.push('cache');\n\t\t}\n\n\t\tfor (const feature of missing) {\n\t\t\tthis.logger.warn(\n\t\t\t\t'router',\n\t\t\t\t`Your project uses ${feature}, but your custom src/fetch.ts does not call the ${feature}() handler. ` +\n\t\t\t\t\t`This feature will not work unless your fetch handler calls it.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tgetDefaultStatusCode(routeData: RouteData, pathname: string): number {\n\t\treturn getDefaultStatusCode(this.manifest, routeData, pathname);\n\t}\n\n\tpublic getManifest() {\n\t\treturn this.manifest;\n\t}\n\n\tlogThisRequest({\n\t\tpathname,\n\t\tmethod,","sourceCodeStart":502,"sourceCodeEnd":538,"githubUrl":"https://github.com/withastro/astro/blob/157c500c38faa7ecf1251adbaeefcd109470d75c/packages/astro/src/core/app/base.ts#L502-L538","documentation":"A custom src/fetch.ts replaces Astro's entire request pipeline. After the first request, Astro compares features the manifest says the project uses (redirects, sessions, actions, middleware, i18n when strategy is not 'manual', cache) against the feature bitmask your handler actually invoked, and warns once for each feature whose handler was never called — that feature silently stops working under your handler.","triggerScenarios":"Adding src/middleware.ts, session config, actions, i18n config with strategy != 'manual', or `cache`/`routeRules` config while the custom src/fetch.ts default export never calls the corresponding middleware(), i18n(), cache(), sessions(), redirects(), actions() handlers that the built-in DefaultFetchHandler pipeline composes.","commonSituations":"Adopting a custom fetch handler to run edge-platform or Hono-style routing logic and forgetting to compose Astro's built-in feature handlers; porting an old handler to a project that later gained middleware or caching.","solutions":["In src/fetch.ts, wrap your dispatch with the feature handlers the warning names, e.g. cache(state, () => middleware(state, ...)) and post-process the response with i18n(state, response)","Or extend the default pipeline instead of replacing it, so all handlers keep running","If you intentionally dropped a feature, remove its source (e.g. delete src/middleware.ts, drop the cache config) so the manifest no longer reports it as used"],"exampleFix":"// before — src/fetch.ts replaces the pipeline; middleware/i18n/cache never run\nexport default async function fetch(request: Request): Promise<Response> {\n  return myCustomRouter(request);\n}\n\n// after — compose the handlers the warning lists\nimport { cache, i18n, middleware } from 'astro/fetch';\n\nexport default async function fetch(request: Request): Promise<Response> {\n  const state = getFetchState(request);\n  return cache(state, async () => {\n    const response = await middleware(state, () => myCustomRouter(request));\n    return i18n(state, response);\n  });\n}","handlingStrategy":"validation","validationCode":"// after adding src/fetch.ts, assert configured features still run.\n// example: middleware sets this header on every response\nconst res = await fetch('http://localhost:4321/');\nif (!res.headers.get('x-ran-middleware')) {\n  throw new Error('custom fetch.ts does not call the middleware() handler');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the custom fetch handler thin: compose Astro's built-in handlers instead of reimplementing routing","Add a smoke test per configured feature (middleware header, i18n redirect, cache hit) that runs against a real request","Re-run the smoke suite whenever adding middleware, i18n, sessions, actions, or cache config"],"tags":["fetch-handler","middleware","i18n","cache","pipeline"],"backgroundTag":"custom-handler-missing-callback","analyzedSha":"157c500c38faa7ecf1251adbaeefcd109470d75c","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}