{"record":{"id":"ab2f5b657af77cc0","repo":"astral-sh/ruff","slug":"cannot-offer-a-fix-when-there-are-multiple-all","errorCode":null,"errorMessage":"Cannot offer a fix when there are multiple __all__ definitions","messagePattern":"Cannot offer a fix when there are multiple __all__ definitions","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs","lineNumber":631,"sourceCode":"\n    let imports = {\n        let mut imports: Vec<&str> = imports\n            .into_iter()\n            .map(ImportBinding::symbol_stored_in_outer_scope)\n            .collect();\n        if imports.is_empty() {\n            bail!(\"Expected import bindings\");\n        }\n        imports.sort_unstable();\n        imports\n    };\n\n    let edits = match dunder_all_exprs {\n        [] => fix::edits::make_redundant_alias(imports.into_iter(), statement),\n        [dunder_all] => {\n            fix::edits::add_to_dunder_all(imports.into_iter(), dunder_all, checker.stylist())\n        }\n        _ => bail!(\"Cannot offer a fix when there are multiple __all__ definitions\"),\n    };\n\n    // Only emit a fix if there are edits.\n    let mut tail = edits.into_iter();\n    let head = tail.next().ok_or(anyhow!(\"No edits to make\"))?;\n\n    let isolation = Checker::isolation(checker.semantic().parent_statement_id(node_id));\n    Ok(Fix::safe_edits(head, tail).isolate(isolation))\n}\n\n/// Returns an iterator over bindings to import statements that appear unused.\n///\n/// The stable behavior is to return those bindings to imports\n/// satisfying the following properties:\n///\n/// - they are not shadowed\n/// - they are not `global`, not `nonlocal`, and not explicit exports (i.e. `import foo as foo`)\n/// - they have no references, according to the semantic model","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs#L613-L649","documentation":"When a F401 unused import should be re-exported via `__all__`, the fixer can only handle zero or one `__all__` definition in the module. Multiple `__all__` assignments make the target of the edit ambiguous, so Ruff refuses to offer a fix.","triggerScenarios":"`fix_by_reexporting` found two or more `__all__` expression definitions in the same module while attempting to add unused-import symbols to `__all__`.","commonSituations":"Large `__init__.py` files where `__all__` is defined more than once (e.g. extended conditionally or split across sections), or generated code that redeclares `__all__`.","solutions":["Consolidate the module to a single `__all__ = [...]` definition, then re-run `ruff --fix`","Manually add the unused symbol to one `__all__` list","Suppress F401 for that import with `# noqa: F401`"],"exampleFix":"# before\n__all__ = ['A']\n__all__ += ['B']  # or a second __all__ = [...]\n# after\n__all__ = ['A', 'B']","handlingStrategy":"validation","validationCode":"# Verify a single __all__ before running the re-export fix:\nimport ast\nalls = [n for n in ast.walk(ast.parse(src))\n        if isinstance(n, ast.Assign)\n        and any(getattr(t, 'id', None) == '__all__' for t in n.targets)]\nassert len(alls) <= 1, 'multiple __all__ definitions will block the fix'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Define __all__ exactly once per module","Use `__all__ += [...]` sparingly; prefer one list literal","Let the F401 re-export fixer manage __all__ entries"],"tags":["ruff","autofix","pyflakes","f401","dunder-all"],"backgroundTag":"autofix-failed-to-apply","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}