{"record":{"id":"d19807b8efc74eaf","repo":"sveltejs/kit","slug":"routes-include-and-routes-exclude-must-be-arrays","errorCode":null,"errorMessage":"routes.include and routes.exclude must be arrays","messagePattern":"routes\\.include and routes\\.exclude must be arrays","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapter-cloudflare/utils.js","lineNumber":95,"sourceCode":"\n\treturn redirects;\n}\n\n/**\n * Generates the [_routes.json](https://developers.cloudflare.com/pages/functions/routing/#create-a-_routesjson-file)\n * file that dictates which routes invoke the Cloudflare Worker.\n * @param {import('@sveltejs/kit').Builder} builder\n * @param {string[]} client_assets\n * @param {string[]} redirects\n * @param {import('./index.js').AdapterOptions['routes']} routes\n * @returns {import('./index.js').RoutesJSONSpec}\n */\nexport function get_routes_json(builder, client_assets, redirects, routes) {\n\tconst include = routes?.include ?? ['/*'];\n\tlet exclude = routes?.exclude ?? ['<all>'];\n\n\tif (!Array.isArray(include) || !Array.isArray(exclude)) {\n\t\tthrow new Error('routes.include and routes.exclude must be arrays');\n\t}\n\n\tif (include?.length === 0) {\n\t\tthrow new Error('routes.include must contain at least one route');\n\t}\n\n\tif (include?.length > 100) {\n\t\tthrow new Error('routes.include must contain 100 or fewer routes');\n\t}\n\n\t/** @type {Set<string>} */\n\tconst transformed_rules = new Set();\n\tfor (const rule of exclude) {\n\t\tif (rule === '<all>') {\n\t\t\ttransformed_rules.add('<build>');\n\t\t\ttransformed_rules.add('<files>');\n\t\t\ttransformed_rules.add('<prerendered>');\n\t\t\ttransformed_rules.add('<redirects>');","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/adapter-cloudflare/utils.js#L77-L113","documentation":"The adapter's `routes` option lets you customize `_routes.json` include/exclude patterns to control which requests invoke the Worker. Both `routes.include` and `routes.exclude` must be arrays (Cloudflare's route-matching format). Passing a string, object, or other non-array value fails this validation at build time.","triggerScenarios":"Configuring adapter options with e.g. `routes: { include: '/api/*' }` (a string instead of array) or `routes: { exclude: 'assets/*' }` — validated inside get_routes_json during adapt.","commonSituations":"Copy-pasting a single route pattern from Cloudflare docs without array brackets; JSON5/JS config mistakes; typing a comma-separated string instead of an array of patterns.","solutions":["Wrap each pattern in an array: routes: { include: ['/*'], exclude: ['/static/*'] }.","Omit the property entirely to use the defaults (include: ['/*'], exclude: ['<all>']).","Verify the adapter option shape against the adapter-cloudflare documentation."],"exampleFix":"// before (svelte.config.js)\nadapter: adapter({ routes: { include: '/api/*' } })\n\n// after\nadapter: adapter({ routes: { include: ['/api/*'] } })","handlingStrategy":"type-guard","validationCode":"const routes = adapterOptions.routes;\nif (routes && (!Array.isArray(routes.include ?? ['/*']) || !Array.isArray(routes.exclude ?? ['<all>']))) {\n  throw new Error('routes.include and routes.exclude must be arrays');\n}","typeGuard":"function isValidRoutesOption(routes) {\n  return routes === undefined || (\n    typeof routes === 'object' && routes !== null &&\n    (routes.include === undefined || Array.isArray(routes.include)) &&\n    (routes.exclude === undefined || Array.isArray(routes.exclude))\n  );\n}","tryCatchPattern":"try {\n  await viteBuild();\n} catch (e) {\n  if (String(e).includes('must be arrays')) {\n    console.error('Wrap routes.include / routes.exclude values in [ ... ]');\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Always write route patterns as arrays of strings in svelte.config.js.","Add a JS/TS config schema check (e.g. zod) around adapter options.","Omit `routes` entirely unless you need custom patterns.","Copy option examples from the official adapter-cloudflare docs, not Cloudflare route docs."],"tags":["cloudflare","adapter-config","routes-json","validation"],"backgroundTag":"invalid-config-type","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}