facebook/docusaurus · error

it should be a RegExp or a string, but received ${from}

Error message

it should be a RegExp or a string, but received ${from}

What it means

Thrown inside the Joi custom validator for themeConfig.algolia.replaceSearchResultPathname.from when the provided value is neither a string nor a RegExp. The validator normalizes string inputs via RegExp.escape and RegExp inputs via .source; anything else (number, object, array, undefined-but-required, boolean) is rejected with the received value interpolated into the message.

Source

Thrown at packages/docusaurus-theme-search-algolia/src/validateThemeConfig.ts:56

    apiKey: Joi.string().required(),
    indexName: Joi.string().required(),
    searchParameters: Joi.object({
      facetFilters: FacetFiltersSchema.optional(),
    })
      .default(DEFAULT_CONFIG.searchParameters)
      .unknown(),
    searchPagePath: Joi.alternatives()
      .try(Joi.boolean().invalid(true), Joi.string())
      .allow(null)
      .default(DEFAULT_CONFIG.searchPagePath),
    replaceSearchResultPathname: Joi.object({
      from: Joi.custom((from) => {
        if (typeof from === 'string') {
          return RegExp.escape(from);
        } else if (from instanceof RegExp) {
          return from.source;
        }
        throw new Error(
          `it should be a RegExp or a string, but received ${from}`,
        );
      }).required(),
      to: Joi.string().required(),
    }).optional(),
    // Ask AI configuration (DocSearch v4 only)
    askAi: Joi.alternatives()
      .try(
        // Simple string format (assistantId only)
        Joi.string(),
        // Full configuration object
        Joi.object({
          assistantId: Joi.string().required(),
          // Optional Ask AI configuration
          indexName: Joi.string().optional(),
          apiKey: Joi.string().optional(),
          appId: Joi.string().optional(),
          searchParameters: Joi.object({

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Provide 'from' as a string (it will be escaped literally) or a RegExp object.
  2. If you serialized config to JSON, restore RegExp objects after parsing (JSON has no RegExp type).
  3. Match it with a 'to' string; both fields are required.

Example fix

// before
algolia: { replaceSearchResultPathname: { from: 'docs/', to: '' } } // works, but if you used a number:
algolia: { replaceSearchResultPathname: { from: 0, to: '' } }
// after
algolia: { replaceSearchResultPathname: { from: /^docs\//, to: '' } }
Defensive patterns

Strategy: type-guard

Validate before calling

const from = cfg.algolia?.replaceSearchResultPathname?.from;
if (typeof from !== 'string' && !(from instanceof RegExp)) {
  throw new Error('replaceSearchResultPathname.from must be string or RegExp');
}

Type guard

const isStringOrRegExp = (v: unknown): v is string | RegExp =>
  typeof v === 'string' || v instanceof RegExp;

Prevention

When it happens

Trigger: Setting replaceSearchResultPathname: { from: 123, to: '' } or from: /pattern/ with a non-RegExp/non-string, or omitting 'from' where Joi marks it required, or passing an array/object.

Common situations: Typing from as a number; passing a string that should be a RegExp literal but quoted wrongly; copying config from JS that lost the RegExp object (e.g. JSON.stringify turned it into {}); misunderstanding the schema.

Related errors


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