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
- Drop `--migrate` and keep `--overwrite` if you want fresh IDs in the target syntax.
- Drop `--overwrite` and keep `--migrate` if you only want to convert existing classic IDs to the new syntax.
- 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
- Use commander's conflicting-flags API to reject this at parse time.
- Document each flag's exact semantics prominently.
- In scripts, never pass both — pick one based on intent.
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
- Invalid --syntax value "${options.syntax}". Valid values: ${
- Invalid package manager choice ${packageManager}. Must be on
- Directory already exists at path=${dest}!
- Heading ids can either be overwritten or migrated, not both
- Invalid command: ${command}
AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12).
Data as JSON: /api/errors/066ef61e5cd6b8a7.
Report an issue: GitHub.