Skip to content

bug(elixir): nvim-lint spec replaces linters_by_ft, dropping linters registered before it #7248

Description

@ChrisGVE

What I checked first

Searched LazyVim issues and discussions for credo, hadolint, linters_by_ft, fish linter. The only related hit is #3808, and its fix (#3809) is what introduced this. Reproduced on a clean lazy.minit install of LazyVim 99970099 (2026-09-08), which is current main for this file.

Neovim version (nvim -v)

NVIM v0.12.5 (Release, LuaJIT 2.1.1788856981)

Operating system/version

macOS 26.6.2 (25G83)

Describe the bug

The lang.elixir extra's nvim-lint spec assigns new tables instead of merging into the ones it receives:

opts = function(_, opts)
  opts.linters_by_ft = {
    elixir = { "credo" },
  }

  opts.linters = {
    credo = { ... },
  }
end,

So every linters_by_ft entry merged before this spec is silently thrown away. In practice that's core's fish = { "fish" }, lang.cmake's cmakelint and lang.docker's hadolint, plus any opts.linters override from an earlier spec. There's no warning, the linters just never run. Extras imported after elixir (go, haskell, kotlin) and user specs survive, which is why it's easy to miss: you only see it by looking at the resolved table.

Steps To Reproduce

  1. Save the repro below as repro.lua, run nvim -u repro.lua, let it install, quit.
  2. nvim -u repro.lua
  3. :lua require("lazy").load({ plugins = { "nvim-lint" } }) print(vim.inspect(vim.tbl_keys(require("lint").linters_by_ft)))

Result: { "elixir" }

Changing only which extras are imported, and in what order:

extras imported, in order linters_by_ft keys
docker dockerfile, fish
docker, elixir elixir
elixir, docker dockerfile, elixir
cmake, docker, elixir elixir

The first, third and fourth rows came from a minimal LazyVim that reuses an installed plugin tree (mason disabled); the "docker, elixir" row reproduces with both that setup and the clean repro.lua below.

Expected Behavior

dockerfile, elixir and fish all present, whatever order the extras are imported in.

A table-form opts would let lazy merge it like the other extras do, e.g.

opts = {
  linters_by_ft = {
    elixir = { "credo" },
  },
  linters = {
    credo = {
      condition = function(ctx)
        return vim.fs.find({ ".credo.exs" }, { path = ctx.filename, upward = true })[1]
      end,
    },
  },
},

Repro

vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()

require("lazy.minit").repro({
  spec = {
    { "LazyVim/LazyVim", import = "lazyvim.plugins" },
    { import = "lazyvim.plugins.extras.lang.docker" },
    { import = "lazyvim.plugins.extras.lang.elixir" },
  },
})

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions