rmagatti / auto-session

A small automated session manager for Neovim
MIT License
1.19k stars 49 forks source link

[BUG] .swp file, corrupted session, esoteric recovery #337

Closed Ben-PH closed 1 month ago

Ben-PH commented 1 month ago

Describe the bug following error on startup:

auto-session ERROR: Error restoring session! The session might be corrupted.
Disabling auto save. Please check for errors in your config. Error:
vim/_editor.lua:0: nvim_exec2()../home/my_name/.local/share/nvim/sessions/%home%my_name%rust%vuvuzella.vim, line 25: Vim(edit):E325: ATTENTION

coming after this message:

2 buffers deleted
Found a swap file by the name "~/.local/state/nvim/swap//%home%my_name%rust%vuvuzella%docker%run_docker.py.swp"
          owned by: my_name   dated: Thu Aug 01 17:25:06 2024
         file name: ~my_name/rust/vuvuzella/docker/run_docker.py
          modified: YES
         user name: my_name   host name: LaptopOfTheseus
        process ID: 145065
While opening file "docker/run_docker.py"
             dated: Fri Aug 02 14:21:12 2024
      NEWER than swap file!

(1) Another program may be editing the same file.  If this is the case,
    be careful not to end up with two different instances of the same
    file when making changes.  Quit, or continue with caution.
(2) An edit session for this file crashed.
    If this is the case, use ":recover" or "vim -r docker/run_docker.py"
    to recover the changes (see ":help recovery").
    If you did this already, delete the swap file "/home/my_name/.local/state/nvim/swap//%home%my_name%rust%vuvuzella%docker%run_docker.py.swp"
    to avoid this message.

Swap file "~/.local/state/nvim/swap//%home%my_name%rust%vuvuzella%docker%run_docker.py.swp" already exists!

additionally, I use barbar, and it doesn't show up the loaded in buffers. :bp and :bn work, but jumping between numbered buffers doesn't. I'm not familiar enough with barbar to know how this might be relevant at a detailed level, but it supports an hypothesis that the feature of auto-session "reopening" the same buffers is not happening as expected.

I run :recover after all that, save, and the file is all good file-wise, but session is still corrupted, and need to manually delete the swap file. Once that's done, session opens as expected.

If I open a session that isn't corrupted, and try to change to the corrupted session, the old sessions buffers do not close, and a single buffer of the opened session is opened.

this is the sessions 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 ~/rust/vuvuzella
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 +17 docker/Dockerfile.node
badd +12 docker/entry.py
badd +1 config/node1.yaml
badd +1 config/node0.yaml
badd +1 config/node2.yaml
badd +51 docker/run_docker.py
argglobal
%argdel
$argadd ~/rust/vuvuzella
edit docker/run_docker.py
argglobal
setlocal fdm=manual
setlocal fde=0
setlocal fmr={{{,}}}
setlocal fdi=#
setlocal fdl=0
setlocal fml=1
setlocal fdn=20
setlocal fen
silent! normal! zE
let &fdl = &fdl
let s:l = 51 - ((50 * winheight(0) + 39) / 79)
if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l
normal! zt
keepjumps 51
normal! 05|
lcd ~/rust/vuvuzella
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
doautoall SessionLoadPost
unlet SessionLoad
" vim: set ft=vim :

To Reproduce Unknown exactly, but this is my best guess:

  1. modify file to setup a .swp file
  2. exit nvim to setup for a swap-file warning
  3. choose open read-only, edit enyway, or recover
  4. see error

Expected behavior

I select a swap-file option (recover, edit anyway, etc), and the session is restored, with the file(s) in question being opened to a buffer accordingly creenshots to help explain your problem.

Baseline (please complete the following information):

-- bindings:

M.auto_session = function() return { { '', 'Autosession search', desc = "Session search", hidden = true }, { '', 'SessionRestore', desc = "Session Restore" } } end



**Additional context**
Add any other context about the problem here.
cameronr commented 1 month ago

Thanks for the detailed report. The main question is how are you exiting nvim with unsaved edits in a swap file? Is it crashing for you or are you exiting in some other way? AFAIK, that should only happen in some significant error situation.

As for the error, it's happening while nvim is sourcing the session and happens on the edit docker/run_docker.py line. Because of the existing swap file error, nvim stops processing the rest of the session file (you can see that by doing echo g:SessionLoad and seeing that it returns 1. That shows it didn't get to the unlet SessionLoad at the end).

We rely on nvim's builtin handling of sourcing a session file so there isn't much we can do about that error. You can suppress swap file warnings by adding A to shortmess but that may make it harder to know if you have unsaved changes after a crash so only set it if understand the ramifications.

Separately, in your auto-session config, opts isn't being used because you defined a config function so none of the options set in opts are actually being used. If you want to use both opts and a custom config function, you have to add opts to the function definition and then pass it to setup like this:

return {
   {
    'rmagatti/auto-session',
    dependencies = {
        'nvim-telescope/telescope.nvim', -- Only needed if you want to use sesssion lens
    },
    opts = {
        auto_session_suppress_dirs = { '~/', '~/Projects', '~/Downloads', '/' },
        auto_session_enable_last_session = true,
        auto_save_enabled = true,
        auto_restore_enabled = true,
        auto_session_use_git_branch = true,

        auto_session_create_enabled = function()
            local cmd = 'git rev-parse --is-inside-work-tree'
            return vim.fn.system(cmd) == 'true\n'
        end,
    },
    config = function(_, opts)
        require('auto-session').setup(opts)
        local wk = require('wk_mappings')
        wk.wk().add(wk.auto_session())
    end,
   },
}

OTOH, if you haven't needed those options, you could also just not set them. Also, auto_save_enabled and auto_restore_enabled are true by default so you don't have to set them true in your config.

Ben-PH commented 1 month ago

Thanks for the detailed report

A small gesture of appreciation for putting in the work and making it freely available

The main question is how are you exiting nvim with unsaved edits in a swap file?

Shutting down my machine, forgetting to save changed buffers. I could probably replicate it by closing the terminal emulator that it's running in as well? Would you like me to confirm these methods?

Separately, in your auto-session config, opts isn't being used because [...]

Didn't realise that. I'm new to lazy.nvim. Thanks.

...from what I gather here, there's not really that much to be done? As I understand things, raw nvim has a process where you can, for example, choose to restore, save the restored state, and that clears the swap file. Perhaps there could be somethnig like a recovery-mode for auto-session? e.g. when something like swap file, corrupted session, etc is detected, auto-session is, in a way, "disabled", giving a chance to go through the recovery process, and then attempt to restart?

cameronr commented 1 month ago

Shutting down my machine, forgetting to save changed buffers. I could probably replicate it by closing the terminal emulator that it's running in as well? Would you like me to confirm these methods?

No, that's not necessary. It's easy to reproduce the case by having unsaved changes and then killing the nvim process.

...from what I gather here, there's not really that much to be done? As I understand things, raw nvim has a process where you can, for example, choose to restore, save the restored state, and that clears the swap file. Perhaps there could be somethnig like a recovery-mode for auto-session? e.g. when something like swap file, corrupted session, etc is detected, auto-session is, in a way, "disabled", giving a chance to go through the recovery process, and then attempt to restart?

While I wish the native swap recovery process was more streamlined, there isn't much we can currently do in this case beyond reporting the error and disabling autosave (so we don't impact overwrite the session on exit). When it happens, I'd recommend resolving the existing swap error(s) however makes the most sense to you then run :SessionRestore again as that should restore the session normally. You may also want to re-enable autosave (if you normally have it on) via ':SessionDisableAutoSave!or:SessionToggleAutoSave`

cameronr commented 1 month ago

Actually, I take all of that back. It is possible for us to ignore errors when sourcing the session by doing:

silent! source <session>

I think that would improve the experience in this case as you'd still get the swap warning (and get to chose an option) but it would continue processing the session. We can even grab vim.v.errmsg and see if an error was generated and still disable autosave in that case. I think that actually makes for a better default experience. The only downside I see is that the error message in vim.v.errmsg isn't quite descriptive as the one we get when the exception gets bubbled up (e.g. it doesn't include the line causing the error). That seems like a small price to pay to continue loading the session which is what I think most users would expect.

I whipped up a test branch if you want to give it a try. You'll have to update your auto-session config as follows:

  -- 'rmagatti/auto-session',
  'cameronr/auto-session',
  branch = 'silent-source',

After changing the config, you'll have to open Lazy and update the plugin to actually pull it down (and restart nvim just to be sure)