astral-sh/ruff · error

Fix introduced a syntax error

Error message

Fix introduced a syntax error

What it means

After applying an autofix, `lint_fix` re-parses the transformed source. If that parse fails, the fix would have introduced invalid syntax, so Ruff reports a fix syntax error (pointing at the offending fix) and returns this error instead of emitting broken code.

Source

Thrown at crates/ruff_linter/src/linter.rs:639

            &suppressions,
        );

        if iterations == 0 {
            has_valid_syntax = parsed.has_valid_syntax();
            has_no_syntax_errors = !diagnostics.iter().any(Diagnostic::is_invalid_syntax);
        } else {
            // If the source code had no syntax errors on the first pass, but
            // does on a subsequent pass, then we've introduced a
            // syntax error. Return the original code.
            if has_valid_syntax && has_no_syntax_errors {
                if let Some(error) = parsed.errors().first() {
                    report_fix_syntax_error(
                        path,
                        transformed.source_code(),
                        error,
                        fixed.identifiers(),
                    );
                    return Err(anyhow!("Fix introduced a syntax error"));
                }
            }
        }

        // Apply fix.
        if let Some(FixResult {
            code: fixed_contents,
            fixes: applied,
            source_map,
        }) = fix_file(&diagnostics, &locator, unsafe_fixes)
        {
            if iterations < MAX_ITERATIONS {
                // Count the number of fixed errors.
                for (id, code, count) in applied.iter() {
                    *fixed.entry(id).or_default(code) += count;
                }

                transformed = Cow::Owned(transformed.updated(fixed_contents, &source_map));

View on GitHub (pinned to 26f38c119c)

Solutions

  1. Read the `report_fix_syntax_error` output to identify the rule producing the bad fix and disable that rule for the file (e.g. `# ruff: noqa` or per-file-ignores).
  2. Retry with `--unsafe-fixes` disabled (or vice versa) to avoid the specific fix class.
  3. Apply fixes rule-by-rule (`--select` one rule at a time) to isolate the interaction.
  4. If it is a fixer bug, minimize the reproducing file and report it upstream to the Ruff repository.

Example fix

// before
$ ruff check --fix --unsafe-fixes module.py
# error: Fix introduced a syntax error

// after: isolate the offending rule
$ ruff check --select RULE_ID module.py  # confirm culprit
$ ruff check --fix --extend-ignore RULE_ID module.py
Defensive patterns

Strategy: try-catch

Try / catch

match run_ruff_fix(file) {
    Err(e) if e.to_string() == "Fix introduced a syntax error" => {
        eprintln!("See the report_fix_syntax_error output above; disable the culprit rule and re-run");
        // fallback: restore from VCS and fix rule-by-rule
        git_checkout(file);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running `ruff check --fix` (via `lint_path` or `lint_stdin`) when a rule's generated fix produces source that fails re-parsing, with `report_fix_syntax_error` printing details of the rule and identifiers.

Common situations: Bugs in rule fix implementations, fixes interacting badly when several rules' fixes combine, fixes applied to unusual syntax patterns the fixer didn't anticipate, or usage of unstable/preview fixes.

Related errors


AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05). Data as JSON: /api/errors/8246b0b1403e5a39. Report an issue: GitHub.