lazy.nvim icon indicating copy to clipboard operation
lazy.nvim copied to clipboard

bug: children `specs` are not properly ignored when disabling a plugin

Open mehalter opened this issue 11 months ago • 36 comments

Did you check docs and existing issues?

  • [X] I have read all the lazy.nvim docs
  • [X] I have updated the plugin to the latest version before submitting this issue
  • [X] I have searched the existing issues of lazy.nvim
  • [X] I have searched the existing issues of plugins related to this issue

Neovim version (nvim -v)

NVIM v0.10.3

Operating system/version

Arch Linux

Describe the bug

When using the specs property in a Lazy plugin specification to add non dependency spec modifications it seems that they are always applied even when the parent plugin is disabled. These specifications should be ignored since the plugin that adds them is no longer enabled

Steps To Reproduce

  1. nvim -u repro.lua, start up the minimal configuration
  2. :Lazy, open lazy and see that plenary.nvim is disabled even though it shouldn't

Expected Behavior

plenary.nvim should not be disabled because lazydev.nvim is disabled which should invalidate all of the children specs under it.

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 = {
    -- add a random plugin as an example
    { "nvim-lua/plenary.nvim" },
    {
      "folke/lazydev.nvim",
      enabled = false, -- disable lazydev so all child specs should be ignored
      specs = {
        -- disable plenary if lazydev is enabled
        { "nvim-lua/plenary.nvim", enabled = false },
      },
    },
  },
}

mehalter avatar Jan 14 '25 20:01 mehalter

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Feb 14 '25 01:02 github-actions[bot]

This isn't stale and is still a problem

mehalter avatar Feb 14 '25 04:02 mehalter

Testing this locally if we change this line https://github.com/folke/lazy.nvim/blob/ac21a639c7ecfc8b822dcc9455deceea3778f839/lua/lazy/core/fragments.lua#L166-L166 to

if plugin.specs and plugin.enabled ~= false then

seems to be working (at least with the minimal repro that OP mentioned, plenary is not disabled when lazydev is disabled and when lazydev is enabled then plenary is disabled). Not confident to submit a PR though.

dpetka2001 avatar Feb 15 '25 17:02 dpetka2001

that would work in this case, but is not the solution, since the parent spec might be enabled elsewhere.

folke avatar Feb 15 '25 21:02 folke

@folke this doesn't appear to fix the problem. Here is a repro.lua that still shows that children specs are being respected even if the plugin is disabled:

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 = {
    -- add a random plugin as an example
    { "LazyVim/LazyVim", import = "lazyvim.plugins" },
    {
      "karb94/neoscroll.nvim", -- add some random plugin
      enabled = false, -- disable plugin, so all child specs should be ignored
      specs = {
        -- disable plenary if plugin is enabled
        { "nvim-lua/plenary.nvim", enabled = false },
      },
    },
  },
}

Could you please reopen this issue?

mehalter avatar Feb 25 '25 16:02 mehalter

This works like it should for me. What do you see different?

Image

folke avatar Feb 25 '25 18:02 folke

I get this, although I do think this is probably because lazy.minit is looking at the latest release of Lazy.nvim. Is there an easy way to tell it to use the latest main?

Image

What led me to this is that I'm still encountering this issue in some cases in my personal configuration which I know is using the latest code on main of Lazy.nvim and want to figure out a minimal configuration to report the issue. Thanks for all your help with this!

mehalter avatar Feb 25 '25 18:02 mehalter

My bad, just made a new release

folke avatar Feb 25 '25 18:02 folke

Yeah, looks like that does resolve the issue with the repro.lua that I sent you. Not sure why some of my specs are still plagued by this in my personal configuration. I'll keep trying to find a simple edge case that breaks it and report back!

mehalter avatar Feb 25 '25 18:02 mehalter

Ah I found something.

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 = {
    -- add a random plugin as an example
    { "LazyVim/LazyVim", import = "lazyvim.plugins" },
    {
      "karb94/neoscroll.nvim", -- add some random plugin
      specs = {
        -- disable plenary if neoscroll is enabled
        { "nvim-lua/plenary.nvim", enabled = false },
      },
    },
  },
  { "karb94/neoscroll.nvim", enabled = false },
}

This isn't the exact type of situation. But this is an example of some incorrect behavior. Consider the idea of something living in the LazyVim extras that has some children specs. If someone is using that extra in their configuration and maybe disable a plugin in their configuration it is not disabling the children specs defined in that extra. This could come up if someone has an extra and is conditionally disabling plugins. This results in the plenary.nvim plugin getting disabled still.

mehalter avatar Feb 25 '25 18:02 mehalter

your example is not correct. it should be under spec

folke avatar Feb 25 '25 18:02 folke

ah yeah ignore me 😅 I will report back once I get something figured out. Sorry for the noise right now!

mehalter avatar Feb 25 '25 18:02 mehalter

Okay, I was able to break down the situation in my configuration:

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 = {
    -- add a random plugin as an example
    { "LazyVim/LazyVim", import = "lazyvim.plugins" },
    {
      "karb94/neoscroll.nvim", -- add some random plugin
      enabled = false,
      specs = {
        {
          "MunifTanjim/nui.nvim",
          optional = true, -- only consider if nui is installed elsewhere
          specs = {
            { -- only configure some neoscroll option if Nui is installed
              -- useful for enabling integrations or whatever with optional plugins
              -- if we get to this point then neoscroll is enabled, so optional isn't necessary
              "karb94/neoscroll.nvim",
              opts = {
                hide_cursor = false,
              },
            },
          },
        },
        -- disable plenary if neoscroll is enabled
        { "nvim-lua/plenary.nvim", enabled = false },
      },
    },
  },
}

here is one I'm confident is incorrect this time 😅 I really hope this is helpful haha

mehalter avatar Feb 25 '25 18:02 mehalter

It seems to have to do with the fact that neoscroll.nvim is also defined as a spec in nui.nvim. If you comment out

{ -- only configure some neoscroll option if Nui is installed
              -- useful for enabling integrations or whatever with optional plugins
              -- if we get to this point then neoscroll is enabled, so optional isn't necessary
              "karb94/neoscroll.nvim",
              opts = {
                hide_cursor = false,
              },
            },

then plenary doesn't get disabled.

dpetka2001 avatar Feb 25 '25 18:02 dpetka2001

Yeah exactly! Even though the children specs should be ignored when the plugin is disabled. The result of this has both neoscroll.nvim and plenary.nvim disabled. So it does properly know that neoscroll should be disabled. But is improperly not ignoring the children specs.

mehalter avatar Feb 25 '25 19:02 mehalter

But this doesn't happen if neoscroll isn't defined as a spec in nui.nvim. The children in that case do get ignored. It has to do with the fact that the inner spec of neoscroll.nvim in nui.nvim somehow messes up the resolution of children specs?

dpetka2001 avatar Feb 25 '25 19:02 dpetka2001

Yup! That's what I think is happening as well

mehalter avatar Feb 25 '25 19:02 mehalter

I've just pushed a change where the dirty plugins are rebuilt right after disabling them. This makes sure that plenary won't get disabled in this case, since disabling the parent will remove the enabled=false frag from plenary.nvim

folke avatar Feb 25 '25 19:02 folke

Thanks for the quick fix @folke ! It looks like there may be some sort of race condition or non-determinism. I do see that the issue is resolved some of the time, but if I keep reopening and closing neovim with the same configuration then I get different behavior. Sometimes it correctly keeps plenary and sometimes it will disable it.

Here is a recording of me opening and closing showing the different behaviors: https://asciinema.org/a/yilUilf6dfGbMv1hdmgMwqTHn

mehalter avatar Feb 25 '25 19:02 mehalter

Yep, can also confirm the behavior is not consistent. Sometimes it's disabled, some times not.

dpetka2001 avatar Feb 25 '25 19:02 dpetka2001

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Mar 28 '25 02:03 github-actions[bot]

This issue isn't stale and is still a problem

mehalter avatar Mar 28 '25 02:03 mehalter

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Apr 28 '25 02:04 github-actions[bot]

This isn't stale

mehalter avatar Apr 28 '25 02:04 mehalter

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar May 29 '25 02:05 github-actions[bot]

Not stale

mehalter avatar May 29 '25 02:05 mehalter

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Jun 29 '25 02:06 github-actions[bot]

Not stale

mehalter avatar Jun 29 '25 02:06 mehalter

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Jul 30 '25 02:07 github-actions[bot]

Not stale

mehalter avatar Jul 30 '25 02:07 mehalter