On master, Credo.Check.Design.DeprecatedChecksConfig reports one false positive for every entry in the :disabled list of a config that is already in the new, recommended format. The output of mix credo gen.config therefore fails the check that ships alongside it.
Environment
- credo
master @ 89457a1608a5b027e508d500f53748aef99d4f1d (reports 1.8.0-dev)
- Elixir 1.18.3 / OTP 27, macOS
- Clean on 1.7.19 (see the control below), so this looks like a regression from the unreleased
DeprecatedChecksConfig work (e5ed4af2, 2026-04-28).
Reproduction
mix new repro && cd repro
# add to deps: {:credo, github: "rrrene/credo", branch: "master", only: [:dev, :test], runtime: false}
mix deps.get
mix credo gen.config # stock config, unedited
mix credo --strict
Actual
5 mods/funs, found 38 software design suggestions.
All 38 are the same shape, one per :disabled entry:
┃ [D] → Using `false` for deactivating check `Credo.Check.Design.DuplicatedCode`
┃ in Credo's config is deprecated, move them to `:disabled` instead.
┃ .credo.exs #(config)
The advice cannot be followed: those checks are already in :disabled, which is what the message asks for. mix credo --strict exits 2, so this fails a build that gates on credo.
Expected
No issues. The generated config is in the map form with :enabled / :disabled keys that this check exists to encourage.
Control on 1.7.19
Same project, same steps, only the dep changed to {:credo, "~> 1.7"}:
5 mods/funs, found no issues.
Cause
ConfigFile.merge_checks/2 folds the :disabled list into :enabled as {check, false} pairs:
https://github.com/rrrene/credo/blob/master/lib/credo/config_file.ex#L391-L395
disabled = disable_check_tuples(checks_other[:disabled])
%{
enabled: checks_other_enabled |> normalize_check_tuples() |> Keyword.merge(disabled),
disabled: checks_other[:disabled] || []
}
with
defp disable_check_tuple({name}), do: {name, false}
defp disable_check_tuple({name, _params}), do: {name, false}
DeprecatedChecksConfig then scans enabled ++ disabled from the validated config and flags any {check, false} it finds:
https://github.com/rrrene/credo/blob/master/lib/credo/check/design/deprecated_checks_config.ex#L62-L72
So it is matching credo's own internal normalization, not anything the user wrote. Every :disabled entry produces exactly one finding, which is why the count tracks the size of that list.
The sibling merge_checks/2 clause just below uses Keyword.drop/2 rather than merging false values, and does not have the problem — that may be the intended shape for both.
Note that the check reads the post-merge "credo.validated_config" assign, so it cannot distinguish the deprecated user-written {Check, false} form from the internal one. Detecting the deprecated format probably has to happen against the raw config file, before normalization.
Workaround
Move Credo.Check.Design.DeprecatedChecksConfig itself to :disabled, or keep the :disabled list empty and rely on omission. Both lose something worth having, which is why I would rather report it than sit on the workaround.
On
master,Credo.Check.Design.DeprecatedChecksConfigreports one false positive for every entry in the:disabledlist of a config that is already in the new, recommended format. The output ofmix credo gen.configtherefore fails the check that ships alongside it.Environment
master@89457a1608a5b027e508d500f53748aef99d4f1d(reports1.8.0-dev)DeprecatedChecksConfigwork (e5ed4af2, 2026-04-28).Reproduction
Actual
All 38 are the same shape, one per
:disabledentry:The advice cannot be followed: those checks are already in
:disabled, which is what the message asks for.mix credo --strictexits 2, so this fails a build that gates on credo.Expected
No issues. The generated config is in the map form with
:enabled/:disabledkeys that this check exists to encourage.Control on 1.7.19
Same project, same steps, only the dep changed to
{:credo, "~> 1.7"}:Cause
ConfigFile.merge_checks/2folds the:disabledlist into:enabledas{check, false}pairs:https://github.com/rrrene/credo/blob/master/lib/credo/config_file.ex#L391-L395
with
DeprecatedChecksConfigthen scansenabled ++ disabledfrom the validated config and flags any{check, false}it finds:https://github.com/rrrene/credo/blob/master/lib/credo/check/design/deprecated_checks_config.ex#L62-L72
So it is matching credo's own internal normalization, not anything the user wrote. Every
:disabledentry produces exactly one finding, which is why the count tracks the size of that list.The sibling
merge_checks/2clause just below usesKeyword.drop/2rather than mergingfalsevalues, and does not have the problem — that may be the intended shape for both.Note that the check reads the post-merge
"credo.validated_config"assign, so it cannot distinguish the deprecated user-written{Check, false}form from the internal one. Detecting the deprecated format probably has to happen against the raw config file, before normalization.Workaround
Move
Credo.Check.Design.DeprecatedChecksConfigitself to:disabled, or keep the:disabledlist empty and rely on omission. Both lose something worth having, which is why I would rather report it than sit on the workaround.