facebook/docusaurus · error · Error

Extension "${ext}" is not allowed. If the redirect extension

Error message

Extension "${ext}" is not allowed.
If the redirect extension system is not good enough for your use case, you can create redirects yourself with the "createRedirects" plugin option.

What it means

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.

Source

Thrown at packages/docusaurus-plugin-client-redirects/src/extensionRedirects.ts:20

 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {
  addTrailingSlash,
  removeSuffix,
  removeTrailingSlash,
} from '@docusaurus/utils-common';
import type {RedirectItem} from './types';

const ExtensionAdditionalMessage =
  'If the redirect extension system is not good enough for your use case, you can create redirects yourself with the "createRedirects" plugin option.';

const validateExtension = (ext: string) => {
  if (!ext) {
    throw new Error(
      `Extension "${ext}" is not allowed.\n${ExtensionAdditionalMessage}`,
    );
  }
  if (ext.includes('.')) {
    throw new Error(
      `Extension "${ext}" contains a "." (dot) which is not allowed.\n${ExtensionAdditionalMessage}`,
    );
  }
  if (ext.includes('/')) {
    throw new Error(
      `Extension "${ext}" contains a "/" (slash) which is not allowed.\n${ExtensionAdditionalMessage}`,
    );
  }
  if (encodeURIComponent(ext) !== ext) {
    throw new Error(
      `Extension "${ext}" contains invalid URI characters.\n${ExtensionAdditionalMessage}`,
    );
  }

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Remove empty/blank entries from fromExtensions and toExtensions arrays in docusaurus.config.
  2. If the array is built dynamically, filter(Boolean) before passing it: extensions.filter(Boolean).
  3. Use only simple extension tokens like 'html' (no leading dot, no slash).

Example fix

// before
fromExtensions: ['html', ''],
// after
fromExtensions: ['html'],
Defensive patterns

Strategy: validation

Validate before calling

function assertExtensions(extensions: string[]) {
  extensions.forEach((ext) => {
    if (!ext) throw new Error(`Extension "${ext}" is not allowed.`);
  });
}
// or sanitize: const safe = extensions.filter(Boolean);

Type guard

const isCleanExtension = (e: unknown): e is string =>
  typeof e === 'string' && e.length > 0 && !e.includes('.') && !e.includes('/')
  && encodeURIComponent(e) === e;

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12). Data as JSON: /api/errors/7a4f0758db8ccd5a. Report an issue: GitHub.