{"record":{"id":"7a4f0758db8ccd5a","repo":"facebook/docusaurus","slug":"extension-ext-is-not-allowed-if-the-redirect","errorCode":null,"errorMessage":"Extension \"${ext}\" is not allowed.\nIf the redirect extension system is not good enough for your use case, you can create redirects yourself with the \"createRedirects\" plugin option.","messagePattern":"Extension \"(.+?)\" is not allowed\\.\nIf the redirect extension system is not good enough for your use case, you can create redirects yourself with the \"createRedirects\" plugin option\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts","lineNumber":20,"sourceCode":" * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport {\n  addTrailingSlash,\n  removeSuffix,\n  removeTrailingSlash,\n} from '@docusaurus/utils-common';\nimport type {RedirectItem} from './types';\n\nconst ExtensionAdditionalMessage =\n  'If the redirect extension system is not good enough for your use case, you can create redirects yourself with the \"createRedirects\" plugin option.';\n\nconst validateExtension = (ext: string) => {\n  if (!ext) {\n    throw new Error(\n      `Extension \"${ext}\" is not allowed.\\n${ExtensionAdditionalMessage}`,\n    );\n  }\n  if (ext.includes('.')) {\n    throw new Error(\n      `Extension \"${ext}\" contains a \".\" (dot) which is not allowed.\\n${ExtensionAdditionalMessage}`,\n    );\n  }\n  if (ext.includes('/')) {\n    throw new Error(\n      `Extension \"${ext}\" contains a \"/\" (slash) which is not allowed.\\n${ExtensionAdditionalMessage}`,\n    );\n  }\n  if (encodeURIComponent(ext) !== ext) {\n    throw new Error(\n      `Extension \"${ext}\" contains invalid URI characters.\\n${ExtensionAdditionalMessage}`,\n    );\n  }","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts#L2-L38","documentation":"Thrown by validateExtension() in @docusaurus/plugin-client-redirects when an extension string in fromExtensions or toExtensions is falsy (empty string, or undefined coerced to string). The validator runs over every extension before generating redirects and rejects empty extensions because they would produce nonsensical redirect rules.","triggerScenarios":"Configuring fromExtensions: [''] or fromExtensions: ['html', ''], or passing a value that ends up as '' (e.g. a stray comma in an array, a templated config producing an empty string). Reached when createFromExtensionsRedirects / createToExtensionsRedirects call extensions.forEach(validateExtension).","commonSituations":"A dynamic config building the extensions array that occasionally pushes an empty string; copy-pasting an example with a trailing comma; an env-var-driven config returning '' when the var is unset.","solutions":["Remove empty/blank entries from fromExtensions and toExtensions arrays in docusaurus.config.","If the array is built dynamically, filter(Boolean) before passing it: extensions.filter(Boolean).","Use only simple extension tokens like 'html' (no leading dot, no slash)."],"exampleFix":"// before\nfromExtensions: ['html', ''],\n// after\nfromExtensions: ['html'],","handlingStrategy":"validation","validationCode":"function assertExtensions(extensions: string[]) {\n  extensions.forEach((ext) => {\n    if (!ext) throw new Error(`Extension \"${ext}\" is not allowed.`);\n  });\n}\n// or sanitize: const safe = extensions.filter(Boolean);","typeGuard":"const isCleanExtension = (e: unknown): e is string =>\n  typeof e === 'string' && e.length > 0 && !e.includes('.') && !e.includes('/')\n  && encodeURIComponent(e) === e;","tryCatchPattern":null,"preventionTips":["Filter empty values out of dynamically built extension arrays with .filter(Boolean).","Hard-code the extensions in config rather than computing them from env vars.","Cover the extensions config with a unit test."],"tags":["plugin-client-redirects","redirects","extensions","validation"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}