Fix: Jupyter Notebook Not Working — Kernel Dead, Module Not Found, and Widget Errors
Quick Answer
How to fix Jupyter errors — kernel fails to start or dies, ModuleNotFoundError despite pip install, matplotlib plots not showing, ipywidgets not rendering in JupyterLab, port already in use, and jupyter command not found.
The Error
You open a notebook and the kernel immediately dies:
The kernel has died, and the automatic restart has failed.Or you install a package and it still can’t be found:
import pandas
ModuleNotFoundError: No module named 'pandas'— even though pip install pandas ran successfully a moment ago.
Or your plot code runs without error but nothing appears in the output cell:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
# Cell completes. No output.Or widgets render as raw text instead of interactive controls:
HBox(children=(IntProgress(value=0, max=100), HTML(value='')))Jupyter sits at the intersection of Python environments, browser rendering, and kernel processes — so errors can originate from any of these three layers. This guide separates them clearly.
Why This Happens
Jupyter runs a kernel (a Python process) separate from the browser frontend. The kernel uses whichever Python binary it was registered with — not necessarily the one you ran pip install with. Packages installed by pip go into the Python environment that pip belongs to; if the kernel uses a different Python, those packages aren’t visible.
Browser-rendered outputs (plots, widgets) require specific notebook extensions to be enabled. Installing ipywidgets with pip isn’t enough — the frontend extension must also be present and compatible with your Jupyter version.
Fix 1: Kernel Fails to Start or Dies
Failed to start the kernel process.
The kernel has died, and the automatic restart has failed.Step 1: Confirm ipykernel is installed in the right environment:
# Activate your virtual environment first, then:
pip install ipykernel
# Register it as a kernel Jupyter can find
python -m ipykernel install --user --name=myenv --display-name "Python (myenv)"After registering, the kernel shows up in the Kernel menu as “Python (myenv)”. Select it and restart.
Step 2: Run with debug logging to see the actual crash reason:
jupyter notebook --debug 2>&1 | head -100
# or for JupyterLab
jupyter lab --debugLook for the real error above the generic “kernel died” message — it’s usually a missing package, a corrupted ipykernel install, or a Python binary that no longer exists.
Step 3: Check for kernel conflicts. List registered kernels:
jupyter kernelspec listSample output:
Available kernels:
python3 /usr/local/share/jupyter/kernels/python3
myenv /home/user/.local/share/jupyter/kernels/myenvIf a kernel points to a Python binary that was deleted (e.g., after removing a venv), remove it:
jupyter kernelspec remove myenvThen re-register if needed.
Step 4: Kernel dies immediately on import — usually a native extension crash. Run the import in terminal first to see the real error:
python -c "import tensorflow"
# Or whatever import crashes the kernelIf it errors in terminal, fix the package error there. If it works in terminal but crashes the kernel, the kernel is using a different Python (see Fix 2).
Step 5: Memory OOM kills the kernel — your code allocates more RAM than available. This is silent: the kernel process is killed by the OS, which Jupyter reports as “kernel died.” Track memory in a cell:
import psutil
process = psutil.Process()
print(f"Memory: {process.memory_info().rss / 1024**3:.2f} GB")Reduce batch sizes, load data in chunks, or add more swap space.
Fix 2: ModuleNotFoundError Despite pip install
This is the most common Jupyter confusion. You run pip install numpy in the terminal, then import numpy fails in the notebook. The cause: your terminal’s pip and the notebook’s kernel belong to different Python environments.
The definitive fix — run pip from inside the notebook, using the same Python as the kernel:
# In a notebook cell — installs into the same Python the kernel uses
import sys
!{sys.executable} -m pip install numpy{sys.executable} expands to the full path of the Python binary running the kernel. This guarantees the package lands where the kernel can find it.
Understand why !pip install can fail:
# In a notebook cell:
!which pip # May point to /usr/bin/pip (system)
!which python # May point to /usr/bin/python (system)
import sys
print(sys.executable) # /home/user/.venv/bin/python ← the actual kernel PythonIf which pip and sys.executable point to different Python installations, any !pip install installs into the wrong place.
Register your virtual environment as a Jupyter kernel — the permanent solution:
# 1. Activate your environment
source .venv/bin/activate # Linux/macOS
.venv\Scripts\activate # Windows
# 2. Install ipykernel inside the environment
pip install ipykernel
# 3. Register it
python -m ipykernel install --user --name=myproject --display-name "My Project"
# 4. Start Jupyter from outside the venv (or inside — doesn't matter)
jupyter labNow select “My Project” from the kernel list. All packages in .venv are available.
Pro Tip: Never rely on the default “Python 3” kernel if you’re using virtual environments. Register every project environment as its own named kernel. It takes 30 seconds and eliminates this confusion permanently. List your registered kernels any time with jupyter kernelspec list.
For the broader Python virtual environment confusion, see Python ModuleNotFoundError in venv.
Fix 3: Matplotlib Plots Not Displaying
import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
# Nothing appearsMatplotlib needs a display backend directive that tells Jupyter how to render figures.
For classic Jupyter Notebook:
%matplotlib inline # Static PNG in output cell — most commonPut this in the first cell of the notebook, before any plotting code. Inline backend renders the figure when the cell finishes executing.
For interactive plots in Jupyter Notebook:
%matplotlib notebook # Interactive (zoom, pan) in classic notebookFor JupyterLab:
# Static inline (works out of the box)
%matplotlib inline
# Interactive (requires ipympl)
%pip install ipympl
%matplotlib widgetplt.show() is usually wrong in notebooks — it flushes the figure buffer, which in some backends closes the figure before it can be rendered in the cell output:
import matplotlib.pyplot as plt
# WRONG — plt.show() can produce blank output in some Jupyter backends
plt.plot([1, 2, 3])
plt.show()
# CORRECT — let the cell end naturally; Jupyter captures the figure automatically
plt.plot([1, 2, 3])
# Cell ends here — figure renders in outputIf you need explicit display control (e.g., multiple figures per cell), use plt.figure() to separate them:
import matplotlib.pyplot as plt
fig1, ax1 = plt.subplots()
ax1.plot([1, 2, 3], label='line 1')
ax1.legend()
plt.show() # Explicitly show fig1
fig2, ax2 = plt.subplots()
ax2.scatter([1, 2, 3], [3, 1, 2], color='red')
plt.show() # Show fig2Figures vanish after plt.close() — make sure you’re not clearing figures in a loop before the cell renders:
# WRONG — closes figures before output renders
for i in range(3):
plt.plot([i, i+1, i+2])
plt.savefig(f'fig_{i}.png')
plt.close() # Destroys the figure
# CORRECT — collect axes instead of closing in a loop
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
for i, ax in enumerate(axes):
ax.plot([i, i+1, i+2])
ax.set_title(f'Plot {i}')
plt.tight_layout()Fix 4: ipywidgets Not Rendering in JupyterLab
You install ipywidgets and tqdm or other widget-based libraries, but they display as raw text:
HBox(children=(IntProgress(value=0, max=100), HTML(value='')))The Python package and the frontend extension are two separate pieces that must both be installed.
For classic Jupyter Notebook (7.x and earlier):
pip install ipywidgets
jupyter nbextension enable --py widgetsnbextension --sys-prefix
# Verify it's enabled
jupyter nbextension listFor JupyterLab 3.x and 4.x:
pip install ipywidgets
# JupyterLab 3+ auto-discovers pip-installed extensions — no extra step needed
# Verify:
jupyter labextension listIf the extension still doesn’t appear, try a full reinstall:
pip uninstall ipywidgets widgetsnbextension jupyterlab-widgets
pip install ipywidgets # Re-installs all threeRestart the JupyterLab server (not just the kernel) after installing extensions. The frontend must reload to pick up new extensions.
tqdm progress bars specifically:
# WRONG — uses wrong tqdm variant
from tqdm import tqdm
for i in tqdm(range(100)):
pass
# CORRECT for Jupyter — uses the auto-detecting variant
from tqdm.auto import tqdm
for i in tqdm(range(100)):
passtqdm.auto automatically selects tqdm.notebook when running inside Jupyter, which renders as a proper HTML progress bar instead of plain text.
Fix 5: Stale Variables and Wrong Output
Notebooks don’t execute sequentially by definition — you can run cells in any order, and variables accumulate in the kernel’s memory across runs. This causes bugs that are hard to reproduce and easy to miss.
Scenario: You define df in cell 2, delete that cell, then run a later cell that uses df. It works — because df is still in kernel memory from the previous run. You share the notebook with a colleague, they run it top-to-bottom, and it fails because cell 2 is gone.
Common Mistake: Sharing a notebook that “works on your machine” but fails for others. The cause is almost always stale kernel state — a variable defined in a deleted cell, or a module imported in a previous session. A notebook is only reproducible if it runs cleanly from top to bottom on a fresh kernel.
Always test with Restart and Run All:
- Jupyter Notebook: Kernel → Restart & Run All
- JupyterLab: Run → Restart Kernel and Run All Cells
This clears all variables and re-executes every cell in order from the top. If the notebook fails during this, it’s broken.
Manually clear specific variables:
del df # Delete one variable
del x, y, z # Delete multipleClear everything:
%reset # Prompts for confirmation
%reset -f # No confirmationCheck what’s currently in memory:
%whos # All variables with type and size
%who # Variable names only%autoreload for development — automatically reloads imported modules when their source files change:
%load_ext autoreload
%autoreload 2 # Reload all modules before each cell execution
import my_module # Changes to my_module.py are picked up automaticallyWithout %autoreload 2, changes to a .py file require restarting the kernel for the import to reflect the update.
Fix 6: jupyter: command not found After Installation
$ jupyter notebook
bash: jupyter: command not foundPip installs Jupyter’s script into a directory that isn’t on your PATH. The fix is always to run via python -m:
python -m jupyter notebook
python -m jupyter labThis bypasses the PATH issue entirely by invoking Jupyter as a Python module.
To find where Jupyter was installed:
pip show jupyter # Shows 'Location:' — the scripts are in ../bin/ from there
# On Linux/macOS:
python -m site --user-scripts # ~/.local/bin on most systems
# Add to PATH permanently (bash):
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrcOn Windows, pip installs scripts to %APPDATA%\Python\Python3x\Scripts. Add this to your PATH via System Properties → Environment Variables. Or just use python -m jupyter notebook.
With uv or pipx (recommended for tools you want globally accessible):
# Install Jupyter globally with uv
uv tool install jupyterlab
# Or with pipx
pipx install jupyterlabBoth manage isolated environments and automatically add the jupyter command to your PATH.
Fix 7: Address Already in Use
OSError: [Errno 98] Address already in useA previous Jupyter server is still running (or a process took port 8888). Three options:
Option 1: Use a different port:
jupyter notebook --port 8890
jupyter lab --port 8890Option 2: Find and kill the existing Jupyter server:
# List all running Jupyter servers
jupyter notebook list
# or
jupyter server list
# Output:
# Currently running servers:
# http://localhost:8888/?token=abc123 :: /home/user/projects
# Kill it
jupyter notebook stop 8888Option 3: Find the process using the port directly:
# Linux/macOS
lsof -i :8888 # Find PID
kill -9 <PID>
# Windows (PowerShell)
netstat -ano | findstr :8888 # Find PID in last column
taskkill /PID <PID> /FFix 8: JupyterLab Extension Not Working
Extension error: JupyterLab X.Y requires @org/extension@>=A.B.C
Build is required: Please rebuild JupyterLab.JupyterLab 3.x and later ship extensions as pip packages (prebuilt). No Node.js or build step required. If you’re seeing build errors, you may be on a very old JupyterLab, or the extension only supports the old system.
Check what’s installed and enabled:
jupyter labextension list # Lists all extensions and their enabled status
pip list | grep jupyter # See all jupyter-related pip packagesFor modern JupyterLab (3.x+) — install extension via pip:
# Example: install the Variable Inspector
pip install lckr-jupyterlab-variableinspector
# Restart JupyterLab — extensions are discovered automaticallyFor legacy extensions that still require a build:
# Requires Node.js
npm install -g nodeenv
jupyter lab buildIf extensions are broken after a JupyterLab upgrade, rebuild from scratch:
pip install --upgrade jupyterlab
jupyter lab clean # Removes cached build artifacts
jupyter lab build # Only needed for legacy extension systemDisable a broken extension without uninstalling it:
jupyter labextension disable @org/broken-extensionStill Not Working?
Trust the Notebook
Jupyter’s security model marks notebooks from untrusted sources as untrusted — JavaScript outputs are suppressed to prevent malicious code from running in your browser. If all outputs are blank but the kernel runs fine:
# Trust a specific notebook
jupyter trust notebook.ipynb
# Or from inside the notebook
from IPython.display import display
# Re-run cells — trusted notebooks render JS outputExport to PDF via nbconvert
jupyter nbconvert --to pdf notebook.ipynbPDF export requires Pandoc and LaTeX:
# macOS
brew install pandoc
brew install --cask mactex-no-gui
# Ubuntu/Debian
sudo apt install pandoc texlive-xetex texlive-fonts-recommended
# Windows: install Pandoc from pandoc.org, then MiKTeX from miktex.orgFor HTML export (no LaTeX required): jupyter nbconvert --to html notebook.ipynb.
Remote Jupyter Over SSH
If you run Jupyter on a remote server and access it in a local browser:
# On the remote server — start Jupyter without opening a browser
jupyter lab --no-browser --port=8888
# On your local machine — forward the remote port
ssh -L 8888:localhost:8888 user@remote-server
# Open http://localhost:8888 in your local browser
# Use the token shown in the remote server's terminal outputLarge Output Cells Slowing Down the Notebook
When a cell produces megabytes of output (e.g., logging from a long training run), the notebook file and browser rendering suffer. Clear outputs before saving:
# Strip output from notebook file
jupyter nbconvert --to notebook --ClearOutputPreprocessor.enabled=True notebook.ipynbOr use %%capture to suppress noisy cell output:
%%capture
# All stdout/stderr from this cell is suppressed
model.fit(X_train, y_train, verbose=1)scikit-learn and NumPy in Notebooks
If sklearn estimators raise shape or dtype errors inside a notebook, confirm the data came through transformations correctly with display(X.shape) and display(df.dtypes). For sklearn Pipeline and NaN errors, see scikit-learn not working. For NumPy broadcasting and dtype issues that surface during data preparation in notebooks, see NumPy not working.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: LightGBM Not Working — Installation Errors, Categorical Features, and Training Issues
How to fix LightGBM errors — ImportError libomp libgomp not found, do not support special JSON characters in feature name, categorical feature index out of range, num_leaves vs max_depth overfitting, early stopping callback changes, and GPU build errors.
Fix: NumPy Not Working — Broadcasting Error, dtype Mismatch, and Array Shape Problems
How to fix NumPy errors — ValueError operands could not be broadcast together, setting an array element with a sequence, integer overflow, axis confusion, view vs copy bugs, NaN handling, and NumPy 1.24+ removed type aliases.
Fix: scikit-learn Not Working — NotFittedError, NaN Input, Pipeline, and ConvergenceWarning
How to fix scikit-learn errors — NotFittedError call fit before predict, ValueError Input contains NaN, could not convert string to float, Pipeline ColumnTransformer mistakes, cross-validation leakage, n_jobs hanging on Windows, and ConvergenceWarning.
Fix: Streamlit Not Working — Session State, Cache, and Rerun Problems
How to fix Streamlit errors — session state KeyError state not persisting, @st.cache deprecated migrate to cache_data cache_resource, file upload resetting, slow app loading on every interaction, secrets not loading, and widget rerun loops.