facebook/docusaurus · error · Error

Options --overwrite and --migrate cannot be used together.\n

Error message

Options --overwrite and --migrate cannot be used together.\nThe --overwrite already re-generates IDs in the target syntax, so the --migrate option wouldn't have any effect.

What it means

Thrown by `writeHeadingIds`'s `validateOptions` when both `--overwrite` and `--migrate` are passed. The two flags are mutually exclusive because `--overwrite` already regenerates heading IDs in the target syntax, making `--migrate` a no-op. Passing both indicates the user misunderstood the semantics.

Source

Thrown at packages/docusaurus/src/commands/writeHeadingIds.ts:75

 */
async function getPathsToWatch(siteDir: string): Promise<string[]> {
  const context = await loadContext({siteDir});
  const plugins = await initPlugins(context);
  return plugins.flatMap((plugin) => plugin.getPathsToWatch?.() ?? []);
}

// TODO Docusaurus v4 - Upgrade commander, use choices() API?
function validateOptions(options: WriteHeadingIDOptions) {
  const validSyntaxValues: HeadingIdSyntax[] = ['classic', 'mdx-comment'];
  if (options.syntax && !validSyntaxValues.includes(options.syntax)) {
    throw new Error(
      `Invalid --syntax value "${
        options.syntax
      }". Valid values: ${validSyntaxValues.join(', ')}`,
    );
  }
  if (options.overwrite && options.migrate) {
    throw new Error(
      "Options --overwrite and --migrate cannot be used together.\nThe --overwrite already re-generates IDs in the target syntax, so the --migrate option wouldn't have any effect.",
    );
  }
}

export async function writeHeadingIds(
  siteDirParam: string = '.',
  files: string[] = [],
  options: WriteHeadingIDOptions = {},
): Promise<void> {
  validateOptions(options);

  const siteDir = await fs.realpath(siteDirParam);

  const patterns = files.length ? files : await getPathsToWatch(siteDir);

  const markdownFiles = (
    await safeGlobby(patterns, {

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Drop `--migrate` and keep `--overwrite` if you want fresh IDs in the target syntax.
  2. Drop `--overwrite` and keep `--migrate` if you only want to convert existing classic IDs to the new syntax.
  3. Re-read the help text to confirm which single flag matches your intent.

Example fix

# before
docusaurus write-heading-ids docs --overwrite --migrate
# after
docusaurus write-heading-ids docs --overwrite
Defensive patterns

Strategy: validation

Validate before calling

if (options.overwrite && options.migrate) {
  throw new Error('--overwrite and --migrate are mutually exclusive');
}

Prevention

When it happens

Trigger: Running `docusaurus write-heading-ids --overwrite --migrate ...` simultaneously.

Common situations: User combines flags hoping to do 'both' operations; copy-pasted command from a tutorial that used both; migration script that layers redundant options.

Related errors


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