Skip to content

Race condition on saving files leading to unsaved content that the system thinks is saved #7595

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

Closed
BaukJ opened this issue Mar 3, 2025 · 3 comments
Labels
bug status:Needs Triage Applied to issues that need triage

Comments

@BaukJ
Copy link

BaukJ commented Mar 3, 2025

Description

When saving or autosaving a file, if the save is kicked off, then the file is edited before the save completes, the system believes the file is saved (you can close the file with no warnings), however the latest edits are not saved.
This is quite a rare condition when saving normally, but I managed to reproduce easily in jupyterlab with autosave turned down.

This means that you could close a file, believing it is up to date, only to find that it has not been fully saved.

The impact should be quite low to users because:

  1. You need to be editing a file during a save operation, then close the file without further edits
  2. Unless copy/pasting, you should at most lose a few characters unless your system is under heavy CPU load

While being a small bug, it could have big implications for things like: jupyterlab/jupyterlab#16892

I also had a look at some other issues, and it may possibly be related to this: #6184

Reproduce

First identified in jupyter lab, however as per their bug report process, ended up reproducing it on jupyter notebook directly.
I managed to reproduce it in jupyter lab without imposing any artificial CPU load, however it's very hard to reproduce it without the load in jupyter notebook.

Dockerfile:

FROM python:3
RUN pip install jupyter
CMD ["jupyter", "notebook", "--ServerApp.allow_origin='*'", "--ServerApp.token=''", "--allow-root", "--ServerApp.ip=0.0.0.0", "--ServerApp.port=8888"]

Test.sh (executable):

#!/usr/bin/env bash
docker build . -tlabi
docker rm -f labc
docker run -d -p 8888:8888 --name labc labi

echo "Now:
- open http://localhost:8888/
- Create a new python file (add some content and save it)
- Now press enter to limit the CPU of this box to make the bug more visible...
"
read
docker update --cpus 0.01 labc
echo "
CPU limited.
Now:
- Type a string of characters into the file (e.g. 123456789). Hit Ctrl+S then quickly add a char or two more.
- Close the file (you should get no warning of unsaved data)
- Open the file <-- BUG: Content is not correct and missing some characters

NOTE: close file/open file can just be a reload of the page
"

Once you have the above files setup, you can just run ./test.sh

To reproduce in jupyterlab:

Dockerfile:

FROM python:3
RUN pip install jupyterlab
CMD ["jupyter", "lab", "--core-mode", "--ServerApp.allow_origin='*'", "--ServerApp.token=''", "--allow-root", "--ServerApp.ip=0.0.0.0", "--ServerApp.port=8888"]

test.sh;

#!/usr/bin/env bash
docker build . -tlabi
docker rm -f labc
docker run -d -p 8888:8888 --name labc labi

echo "Now:
- open http://localhost:8888/lab
- goto settings -> Settings Editor -> Document Manager
- Ensure Autosave is checked and interval is short (e.g. 3s)
- Open new python file
- Now press enter to limit the CPU of this box to make the bug more visible...
"
read
docker update --cpus 0.01 labc
echo "
CPU limited.
Now:
- Slowly type a string of characters into the python files (e.g. 123456789). Stop when autosave kicks in and the modified cirle disappears
- Close the file
- Open the file <-- BUG: Content is not correct and missing some characters

NOTE: You can get the same bug if you disable autosave, type the characters, then type Ctrl+S and some more characters until the save icon disappears.
"

Expected behavior

When saving a file, the state of the file at save time is known.

e.g.:

In the examples above, I should be warned about unmodified files before closing as the new content has not actually been saved.

Context

I've reproduced this in AWS sagemaker, but also locally on this setup:

WIndows 11,
WSL,
Ubuntu 24.04
Docker 26.1.3
Jupyter notebook version: 7.3.2
Browser version: Chrome 133.0.6943.127

Troubleshoot Output
$PATH:
      /usr/local/bin
      /usr/local/sbin
      /usr/local/bin
      /usr/sbin
      /usr/bin
      /sbin
      /bin

sys.path:
/usr/local/bin
/usr/local/lib/python313.zip
/usr/local/lib/python3.13
/usr/local/lib/python3.13/lib-dynload
/usr/local/lib/python3.13/site-packages

sys.executable:
/usr/local/bin/python3.13

sys.version:
3.13.2 (main, Feb 25 2025, 05:25:21) [GCC 12.2.0]

platform.platform():
Linux-5.15.167.4-microsoft-standard-WSL2-x86_64-with-glibc2.36

which -a jupyter:
/usr/local/bin/jupyter
/usr/local/bin/jupyter

pip list:
Package Version
------------------------- --------------
anyio 4.8.0
argon2-cffi 23.1.0
argon2-cffi-bindings 21.2.0
arrow 1.3.0
asttokens 3.0.0
async-lru 2.0.4
attrs 25.1.0
babel 2.17.0
beautifulsoup4 4.13.3
bleach 6.2.0
certifi 2025.1.31
cffi 1.17.1
charset-normalizer 3.4.1
comm 0.2.2
debugpy 1.8.12
decorator 5.2.1
defusedxml 0.7.1
executing 2.2.0
fastjsonschema 2.21.1
fqdn 1.5.1
h11 0.14.0
httpcore 1.0.7
httpx 0.28.1
idna 3.10
ipykernel 6.29.5
ipython 9.0.1
ipython_pygments_lexers 1.1.1
ipywidgets 8.1.5
isoduration 20.11.0
jedi 0.19.2
Jinja2 3.1.5
json5 0.10.0
jsonpointer 3.0.0
jsonschema 4.23.0
jsonschema-specifications 2024.10.1
jupyter 1.1.1
jupyter_client 8.6.3
jupyter-console 6.6.3
jupyter_core 5.7.2
jupyter-events 0.12.0
jupyter-lsp 2.2.5
jupyter_server 2.15.0
jupyter_server_terminals 0.5.3
jupyterlab 4.3.5
jupyterlab_pygments 0.3.0
jupyterlab_server 2.27.3
jupyterlab_widgets 3.0.13
MarkupSafe 3.0.2
matplotlib-inline 0.1.7
mistune 3.1.2
nbclient 0.10.2
nbconvert 7.16.6
nbformat 5.10.4
nest-asyncio 1.6.0
notebook 7.3.2
notebook_shim 0.2.4
overrides 7.7.0
packaging 24.2
pandocfilters 1.5.1
parso 0.8.4
pexpect 4.9.0
pip 24.3.1
platformdirs 4.3.6
prometheus_client 0.21.1
prompt_toolkit 3.0.50
psutil 7.0.0
ptyprocess 0.7.0
pure_eval 0.2.3
pycparser 2.22
Pygments 2.19.1
python-dateutil 2.9.0.post0
python-json-logger 3.2.1
PyYAML 6.0.2
pyzmq 26.2.1
referencing 0.36.2
requests 2.32.3
rfc3339-validator 0.1.4
rfc3986-validator 0.1.1
rpds-py 0.23.1
Send2Trash 1.8.3
setuptools 75.8.2
six 1.17.0
sniffio 1.3.1
soupsieve 2.6
stack-data 0.6.3
terminado 0.18.1
tinycss2 1.4.0
tornado 6.4.2
traitlets 5.14.3
types-python-dateutil 2.9.0.20241206
typing_extensions 4.12.2
uri-template 1.3.0
urllib3 2.3.0
wcwidth 0.2.13
webcolors 24.11.1
webencodings 0.5.1
websocket-client 1.8.0
widgetsnbextension 4.0.13

Command Line Output
# Normal output:
[I 2025-03-03 17:56:17.570 ServerApp] Saving file at /a.py
[I 2025-03-03 17:58:02.134 ServerApp] Saving file at /a.py
@krassowski
Copy link
Member

as per their bug report process

oh, we need to clarify that. This report should probably go to JupyterLab as this is where to code is.

@BaukJ
Copy link
Author

BaukJ commented Mar 3, 2025

Thanks
I've not dug into the codebases, and I'm probably quite ignorant to the whole jupyter architecture and repo structure, I just assumed lab was an abstraction over other repos including this one.

Jupyter_server would be where the actual save happens, but I assume this is a client/fronted issue.

If you think it should be raised in jupyterlab I can re-raise there and close this off.

@andrii-i
Copy link
Contributor

andrii-i commented Mar 4, 2025

Hi @BaukJ. Thank you for creating this issue. As discussed, it should be tracked in JupyterLab repo. I have already created a duplicate issue in JupyterLab repo, let's use it to continue the discussion and track this problem jupyterlab/jupyterlab#17365

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug status:Needs Triage Applied to issues that need triage
Projects
None yet
Development

No branches or pull requests

3 participants