Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autocmd errors when starting a session in a cwd #409

Closed
rbhanot4739 opened this issue Feb 20, 2025 · 14 comments · Fixed by #422
Closed

Autocmd errors when starting a session in a cwd #409

rbhanot4739 opened this issue Feb 20, 2025 · 14 comments · Fixed by #422

Comments

@rbhanot4739
Copy link

Hello, Sometimes I see the following error message when I start neovim in a particular directory, and further session saving does not work. Its only after I delete the session files and start fresh a nbew session is created and things get normal. It looks like session is getting corrupted somehow.

I have not seen a pattern to this but this happens once in a while with me.

auto-session ERROR: Error restoring session, disabling auto save.

Error: vim/_editor.lua:0: VimEnter Autocommands for "*"..script nvim_exec2() called at VimEnter Autocommands for "*":0../Users/rbhanot/.local/share/nvim/sessions/%2FUsers%2Frbhanot%2Fdevelopment%2Fwork%2Fmultiproducts%2Fliscm-satellite-server%2Fliscm-satellite-server%7Cmaster.vim, line 182: Vim(normal):E490: No fold found
@cameronr
Copy link
Collaborator

Thanks for the report. The session isn't getting corrupted but there is an error when nvim tries to load the session related to restoring a fold. I have also seen this on occasion but haven't been able to get it to happen consistently enough to track down (I also don't really use folds).

Can you share any fold configuration (values of foldlevel, foldlevelstart, foldexpr, foldmethod) and any plugins you use that interact with folding?

And the next time it happens, can you post the contents of the session file (e.g. `../Users/rbhanot/.local/share/nvim/sessions/%2FUsers%2Frbhanot%2Fdevelopment%2Fwork%2Fmultiproducts%2Fliscm-satellite-server%2Fliscm-satellite-server%7Cmaster.vim)?

@rbhanot4739
Copy link
Author

Here it is; it happened again today, but with a different session.

16:38:20 msg_show Error detected while processing VimEnter Autocommands for "*":
auto-session ERROR: Error restoring session, disabling auto save.
Error: vim/_editor.lua:0: VimEnter Autocommands for "*"..script nvim_exec2() called at VimEnter Autocommands for "*":0../Users/rbhanot/.local/share/nvim/sessions/%2FUsers%2Frbhanot%2F%2Econfig%2Fnvim.vim, line 75: Vim(setlocal):E518: Unknown option: eventignorewin=
foldlevel = 20
foldlevelstart = 20
foldexpr = v:lua.require'lazyvim.util'.ui.foldexpr()
foldmethod = expr

Here are the contents of the session file

let SessionLoad = 1
let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1
let v:this_session=expand("<sfile>:p")
silent only
silent tabonly
cd ~/.config/nvim
if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''
  let s:wipebuf = bufnr('%')
endif
let s:shortmess_save = &shortmess
if &shortmess =~ 'A'
  set shortmess=aoOA
else
  set shortmess=aoO
endif
badd +65 ~/.config/nvim/lua/plugins/util-plugins.lua
badd +6 ~/.config/nvim/lua/plugins/colorscheme.lua
badd +6 ~/.config/nvim/lua/plugins/refector.lua
badd +28 ~/.config/nvim/lua/config/lazy.lua
badd +11 ~/.config/nvim/lua/plugins/git.lua
badd +56 ~/.config/nvim/lua/plugins/snacks.lua
badd +34 ~/.config/nvim/lua/config/options.lua
badd +44 ~/.config/nvim/lua/config/keymaps.lua
badd +2 ~/.config/nvim/lua/plugins/multi-cursors.lua
badd +76 ~/.config/nvim/lua/plugins/lsp-tools.lua
badd +59 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/init.lua
badd +52 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/types.lua
badd +62 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/source/files.lua
badd +725 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/config/sources.lua
badd +6 ~/.config/nvim/lua/disabled.lua
badd +45 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/core/picker.lua
badd +19 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/core/preview.lua
badd +23 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/picker/config/defaults.lua
badd +19 ~/.local/share/nvim/lazy/snacks.nvim/lua/snacks/gitbrowse.lua
badd +13 ~/.config/nvim/lua/plugins/markdown.lua
badd +1 ~/.config/nvim/lua/plugins/telescope.lua
badd +36 ~/.config/nvim/lua/plugins/term.lua
badd +98 ~/.config/nvim/lua/plugins/mini.lua
badd +18 ~/.config/nvim/lua/plugins/nvim-cmp.lua
badd +34 ~/.config/nvim/lua/plugins/blink-cmp.lua
argglobal
%argdel
edit ~/.config/nvim/lua/plugins/blink-cmp.lua
argglobal
balt ~/.config/nvim/lua/plugins/snacks.lua
setlocal keymap=
setlocal noarabic
setlocal autoindent
setlocal nobinary
setlocal nobreakindent
setlocal breakindentopt=
setlocal bufhidden=
setlocal buflisted
setlocal buftype=
setlocal nocindent
setlocal cinkeys=0{,0},0),0],:,0#,!^F,o,O,e
setlocal cinoptions=
setlocal cinscopedecls=public,protected,private
setlocal cinwords=if,else,while,do,for,switch
setlocal colorcolumn=
setlocal comments=:---,:--
setlocal commentstring=--\ %s
setlocal complete=.,w,b,u,t
setlocal completefunc=
setlocal completeslash=
setlocal concealcursor=
setlocal conceallevel=2
setlocal nocopyindent
setlocal nocursorbind
setlocal nocursorcolumn
setlocal cursorline
setlocal cursorlineopt=number,line
setlocal define=\\<function\\�|\\<local\\%(\\s\\+function\\)\\=
setlocal nodiff
setlocal eventignorewin=
setlocal expandtab
if &filetype != 'lua'
setlocal filetype=lua
endif
setlocal fixendofline
setlocal foldcolumn=0
setlocal foldenable
setlocal foldexpr=v:lua.require'lazyvim.util'.ui.foldexpr()
setlocal foldignore=#
setlocal foldlevel=20
setlocal foldmarker={{{,}}}
setlocal foldmethod=expr
setlocal foldminlines=1
setlocal foldnestmax=20
setlocal foldtext=
setlocal formatexpr=v:lua.require'lazyvim.util'.format.formatexpr()
setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s*
setlocal formatoptions=jlcnq
setlocal iminsert=0
setlocal imsearch=-1
setlocal includeexpr=tr(v:fname,'.','/')
setlocal indentexpr=nvim_treesitter#indent()
setlocal indentkeys=0{,0},0),0],:,0#,!^F,o,O,e,0=end,0=until
setlocal noinfercase
setlocal iskeyword=@,48-57,_,192-255
setlocal linebreak
setlocal nolisp
setlocal lispoptions=
setlocal list
setlocal matchpairs=(:),{:},[:]
setlocal modeline
setlocal modifiable
setlocal nrformats=bin,hex
setlocal number
setlocal numberwidth=4
setlocal omnifunc=v:lua.vim.lsp.omnifunc
setlocal nopreserveindent
setlocal nopreviewwindow
setlocal quoteescape=\\
setlocal noreadonly
setlocal relativenumber
setlocal norightleft
setlocal rightleftcmd=search
setlocal scrollback=-1
setlocal noscrollbind
setlocal scrolloff=4
setlocal shiftwidth=2
setlocal signcolumn=yes
setlocal smartindent
setlocal smoothscroll
setlocal softtabstop=0
setlocal spell
setlocal spellcapcheck=[.?!]\\_[\\])'\"\\t\ ]\\+
setlocal spellfile=
setlocal spelllang=en_us
setlocal spelloptions=noplainbuffer
setlocal statuscolumn=%!v:lua.require'snacks.statuscolumn'.get()
setlocal statusline=%#lualine_a_normal#\ NORMAL\ %#lualine_transitional_lualine_a_normal_to_lualine_c_normal#%<%#lualine_c_normal#%=%#lualine_transitional_lualine_a_normal_to_lualine_c_normal#%#lualine_a_normal#\ lua\ 󰢱\ \ 
setlocal suffixesadd=.lua
setlocal swapfile
setlocal synmaxcol=3000
if &syntax != ''
setlocal syntax=
endif
setlocal tabstop=2
setlocal tagfunc=v:lua.vim.lsp.tagfunc
setlocal textwidth=0
setlocal undofile
setlocal varsofttabstop=
setlocal vartabstop=
setlocal virtualedit=block
setlocal winbar=%<%#lualine_c_filetype_MiniIconsAzure_normal#\ 󰢱\ %#lualine_c_normal#%#lualine_c_normal#%#lualine_c_normal#\ blink-cmp.lua\ %#lualine_c_normal#%=%#lualine_x_16_normal#\ 󱉭\ \ nvim\ %#lualine_c_normal#%#lualine_c_normal#\ lua/plugins\ %#lualine_transitional_lualine_a_normal_to_lualine_c_normal#%#lualine_a_normal#\ open\ buffers:\ 25\ 
setlocal winblend=0
setlocal nowinfixbuf
setlocal nowinfixheight
setlocal nowinfixwidth
setlocal winhighlight=
setlocal wrap
setlocal wrapmargin=0
1
normal! zo
8
normal! zo
45
normal! zo
68
normal! zo
79
normal! zo
let s:l = 34 - ((22 * winheight(0) + 13) / 27)
if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l
normal! zt
keepjumps 34
normal! 04|
tabnext 1
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
  silent exe 'bwipe ' . s:wipebuf
endif
unlet! s:wipebuf
set winheight=1 winwidth=20
let &shortmess = s:shortmess_save
let s:sx = expand("<sfile>:p:r")."x.vim"
if filereadable(s:sx)
  exe "source " . fnameescape(s:sx)
endif
let &g:so = s:so_save | let &g:siso = s:siso_save
set hlsearch
nohlsearch
doautoall SessionLoadPost
unlet SessionLoad
" vim: set ft=vim :

@cameronr
Copy link
Collaborator

That looks like a different error as it's saying eventignorewin is an unknown option. It looks like that option was added very recently. Did you save a session with a nightly binary and then load it with release binary?

@rbhanot4739
Copy link
Author

Oh yeah, you are right. I will keep an eye on it and will update if I encounter the original error again.

@dvelyk
Copy link

dvelyk commented Mar 29, 2025

I'm encountering this issue as well. I think it is related at least in part to the speed of the service providing foldexpr.

I use an LSP for languages like lua, and set foldexpr = "v:lua.vim.lsp.foldexpr()" on LspAttach if the LSP supports textDocument/foldingRange. However, most LSPs take a moment to initialize, even on smaller projects. They aren't available at the time neovim starts and the session is loaded. The No fold found error is therefore accurate — no fold exists at that time, but will become available after the LSP (or service that provides folds) loads.

I'm not familiar enough with the internals of this plugin or neovim to know what solutions to this conundrum might be viable. Is it possible to delay loading folds when restoring a session? That might not be a great user experience, but at least the folds would be preserved.

Alternatively, since folds currently aren't restored in these cases anyway, I'd prefer that information simply be discarded from the session if foldexpr is provided by a slow service. That way, I'm not interrupted by the error when restoring the session.

Thanks very much for this great plugin!

@cameronr
Copy link
Collaborator

Ahh, very interesting. I can reproduce this by setting foldmethod=expr and foldexpr=v:lua.vim.lsp.foldexpr() in a project with a language server.

It looks like this is likely a core neovim bug because loading the session via nvim -S (or sourcing the session) shows the same error:

Image

Possibly related bugs: vim/vim#15813, neovim/neovim#2018, neovim/neovim#28692, with a suggestion to ignore fold "errors" on session restore.

That said, we could possibly work around it. Here are the possible options in my mind:

  1. Add a config option ignore_restore_errors that doesn't raise an error if there's any kind of problem on restore. the underlying code would always load sessions via silent! source. This was suggested in [BUG] Error restoring session! ... Vim(help):E661: Sorry, no help for #325
  2. The way the code works now is that it first tries to load a session via silent source. If that throws an error, it loads it again silent! source which will continue loading the session even if it encounters an error and then it displays the error returned by the first silent source call. We could have some special checking that looks at the error message and ignores it if it's a fold error so the whole session is loaded and we won't raise the error in that case.
  3. ? some other option ?

@rmagatti any thoughts?

fwiw, as much as I don't like special handling, I lean towards option 2. It would look something like:

  if not success then
    if result and string.find(result, "E490: No fold found") then
      Lib.logger.debug "Ignoring fold error"
    else
      Lib.logger.error([[
Error restoring session, disabling auto save.
Error: ]] .. result)
      Config.auto_save = false
      return false
    end
  end

@rmagatti
Copy link
Owner

I don't love the special handling proposed either; what makes an error in restoring folds different than say an error using a nil variable somewhere? I think there are a couple of potentially better options If I understand the issue card correctly:

  1. Expose a behaviour hook where the user implements and returns true or false for whether the session should restore when there is an error or not. The user can then check for and or just decide to return "true" for restoring the session regardless of error and thus not disabling auto save.
  2. A config for disabling auto-save on error or not (if that doesn't already exist)

@cameronr
Copy link
Collaborator

cameronr commented Mar 30, 2025

I think the fold errors are "special" in the sense that there's known issue with the underlying session code so "false" errors are likely / expected to be generated.

As I think about it a bit more, I think the components are:

  1. How much of the session should be restored? Sourcing a session with silent source will stop on the first error while silent! source will continue loading the session after an error
  2. What message, if any, to surface to the user if there's an error during restore?
  3. What happens to the auto_save config value if there's an error?
  4. How much configurability should there be?
  5. What should the defaults be?

At least for me, I always want to restore as much of the session as possible (i.e. never stop on first error). I don't want to see any fold errors (no message, no disabling auto-save) but I do want to see other errors and disable auto-save in that case. But I also understand others might want it to work differently.

My proposal is to add config option, restore_error_handler, that is a function that's called when there's an error and it is responsible for displaying any message and it should return false to disable auto_save and true to keep it enabled. The default implementation would special case the fold error and show no message (would debug log) and return true in that case but would show all other errors and return false. The user can provide their own function if they want to change the behavior, e.g. showing all error messages, never disabling auto-save, etc.

edit: coded up my proposal, linked below

@kcayme
Copy link

kcayme commented Mar 31, 2025

I noticed consistently encountering this issue when I changed from vim.o.foldmethod="indent" to vim.o.foldmethod="expr" with vim.o.foldexpr="v:lua.vim.treesitter.foldexpr()" or vim.o.foldexpr="v:lua.vim.lsp.foldexpr()". Also, options like vim.opt.scrolloff always set to 0 even though it's 999 in my config whenever this error occurs, though not sure yet if this is really the cause.

This error could probably be ignored or logged as warn (or at least what error message should be ignored) via option since I prefer the session restored regardless of the fold error.

@cameronr
Copy link
Collaborator

cameronr commented Mar 31, 2025

@kcayme Same, foldmethod=expr and foldexpr=v:lua.vim.lsp.foldexpr() consistently repros for me. And I agree on ignoring the fold errors :)

If you want, you can try my branch by updating your auto-session config (assuming you use lazy.nvim):

-- 'rmagatti/auto-session',
'cameronr/auto-session',
branch = 'restore-error-handler',

Then you just need to update the plugin and restart nvim. Let me know if it works for you.

@kcayme
Copy link

kcayme commented Mar 31, 2025

thanks @cameronr ! was able to clone it with branch = "restore-error-handler" and its working fine now and scrolloff issue gone

@cameronr
Copy link
Collaborator

Whoops, sorry about the paste error (fixed above). Glad to hear it's working!

@PrayagS
Copy link

PrayagS commented Apr 1, 2025

Can confirm that @cameronr's fork fixes the issue for me. Root cause was the same i.e. using foldexpr=v:lua.vim.lsp.foldexpr().

PrayagS added a commit to PrayagS/dotfiles that referenced this issue Apr 1, 2025
Thanks to a recent post on r/neovim[^1], it seems
like nvim-ufo is not really needed anymore.

Now the config is set as follows,
1. set `foldexpr` to treesitter in opts.lua
2. use `vim.lsp.foldexpr` when an LSP server is
attached and the client supports folding.

This commit also removes statuscol.nvim which is
replaced by the statuscolumn module in snacks.nvim.

Post this change and given neovim v0.11, restoring
sessions is broken due to a race condition between
restoring and the LSP server being ready[^2].

As a workaround, the version of auto-session is
replaced with a fork that has the required fix[^3].

[^1]: https://www.reddit.com/r/neovim/comments/1jmqd7t/sorry_ufo_these_7_lines_replaced_you
[^2]: rmagatti/auto-session#409
[^3]: rmagatti/auto-session#409 (comment)

Signed-off-by: PrayagS <[email protected]>
@cameronr
Copy link
Collaborator

cameronr commented Apr 2, 2025

@kcayme @PrayagS This is now merged so you can switch back to the main fork. thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants