facebook/docusaurus · error · Error

${formattedError}

Error message

${formattedError}

What it means

Thrown by `validateConfig` when Joi's `ConfigSchema.validate` rejects the user's docusaurus.config. Non-unknown-field errors are concatenated, and if any `object.unknown` details exist, an extra message lists them and points users at the `customFields` escape hatch. It is the single chokepoint for all site config schema failures.

Source

Thrown at packages/docusaurus/src/server/configValidation.ts:671

    const unknownFields = error.details.reduce((formattedError, err) => {
      if (err.type === 'object.unknown') {
        return `${formattedError}"${err.path.reduce((acc, cur) =>
          typeof cur === 'string' ? `${acc}.${cur}` : `${acc}[${cur}]`,
        )}",`;
      }
      return formattedError;
    }, '');
    let formattedError = error.details.reduce(
      (accumulatedErr, err) =>
        err.type !== 'object.unknown'
          ? `${accumulatedErr}${err.message}\n`
          : accumulatedErr,
      '',
    );
    formattedError = unknownFields
      ? `${formattedError}These field(s) (${unknownFields}) are not recognized in ${siteConfigPath}.\nIf you still want these fields to be in your configuration, put them in the "customFields" field.\nSee https://docusaurus.io/docs/api/docusaurus-config/#customfields`
      : formattedError;
    throw new Error(formattedError);
  }

  postProcessDocusaurusConfig(value);

  return value;
}

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Read the printed field list — each unrecognized field is quoted with its path (`.foo.bar`) — and remove or rename it.
  2. Move genuinely custom, non-Docusaurus data into the `customFields` object instead of the config root.
  3. Run `pnpm docusaurus start` again after each fix to surface remaining errors (abortEarly:false reports all at once).
  4. Cross-check the field against https://docusaurus.io/docs/api/docusaurus-config for your version.

Example fix

// before (wrong: typo + unknown key)
export default {
  tilte: 'My Site',
  myCustomThing: 42,
};
// after
export default {
  title: 'My Site',
  customFields: { myCustomThing: 42 },
};
Defensive patterns

Strategy: validation

Validate before calling

import {ConfigSchema} from '@docusaurus/types'; // or import the schema if exposed
// Pre-validate in a CI script:
const {error} = ConfigSchema.validate(userConfig, {abortEarly: false, allowUnknown: false});
if (error) console.error(error.details.map(d => d.message).join('\n'));

Type guard

function isKnownConfigKey(key: string): boolean {
  // maintain a set of valid root keys for your Docusaurus version
  const known = new Set(['title','url','baseUrl','i18n','presets','plugins','themes','customFields'/*,...*/]);
  return known.has(key);
}

Try / catch

try {
  const cfg = await loadConfig(siteConfigPath);
  start(cfg);
} catch (e) {
  if (e instanceof Error && /not recognized|customFields/.test(e.message)) {
    console.error('Config schema error — fix unknown fields:', e.message);
  }
  throw e;
}

Prevention

When it happens

Trigger: Any `ConfigSchema.validate(config, {abortEarly:false})` failure: typos in top-level keys (e.g. `tilte` instead of `title`), wrong types (e.g. `url: 123`), or arbitrary unrecognized root keys. The code at configValidation.ts:652-671 collects all Joi details and re-throws a single composed Error.

Common situations: Misspelled config keys; passing plugin options at the root instead of via presets/plugins; upgrading Docusaurus and using a removed/renamed config field; copy-pasting a v2 config into a v3 site.

Related errors


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