What's happening here?
I know this error is infuriating. You're running your Python project, and suddenly it dies with:
ImportError: cannot import name 'soft_unicode' from 'markupsafe'
This tripped me up the first time too. The short story: soft_unicode was a function in older versions of MarkupSafe (2.0.x and earlier). In MarkupSafe 2.1.0, it was removed. Some packages—especially older versions of Flask, Jinja2, or WTForms—still try to import it. Bingo, you're stuck.
I've seen this most often when someone starts a new project with pip install flask in late 2023 or 2024, and pip grabs the newest MarkupSafe (2.1.x) but an older Jinja2 (like 3.0.x). Or you upgrade MarkupSafe and forget your environment has a pinned dependency.
Fix 1: The 30-second fix — Pin MarkupSafe to a compatible version
Skip the deep dive if you just want things working now. The fastest fix is to install a version of MarkupSafe that still has soft_unicode. Run this in your terminal:
pip install markupsafe==2.0.1
Then restart your Python app. That's it.
Why 2.0.1? Because it's the last version before the removal. Some people try 2.1.0, but that's the one that caused the problem. So don't go higher than 2.0.1 for now.
Fix 2: The 5-minute fix — Upgrade your project dependencies
Pinning is a band-aid. Better to fix the real issue: your other packages need to catch up. Here's how:
- Upgrade Flask and friends – Flask 2.3.x+ and Jinja2 3.1.x+ no longer rely on
soft_unicode. Run: - Check your requirements.txt – If you're using one, update the version numbers for Jinja2 and MarkupSafe to their latest:
- Test it – Run your app again. If the error's gone, you're good.
pip install --upgrade flask jinja2 wtforms
flask>=2.3
jinja2>=3.1.2
markupsafe>=2.1.0
I've seen this fix work for 9 out of 10 cases. The one that doesn't? A package you didn't expect is pulling in an old Jinja2. That leads to fix 3.
Fix 3: The 15+ minute fix — Hunt down the culprit package
Sometimes upgrading Flask and Jinja2 doesn't cut it because an indirect dependency—something like databricks-connect, airflow, or an old pandas-profiling—pulls in an outdated Jinja2 that still wants soft_unicode.
- Find who's importing – Run this to trace the call:
- List your installed packages – Check what's dragging in old Jinja2:
- Check dependency tree – Use
pipdeptreeto see the mess: - Fix it – Two options:
- Upgrade that package to a version that supports Jinja2 3.1+.
- Or pin MarkupSafe to 2.0.1 as a temporary workaround (see fix 1).
python -c "import markupsafe; print(markupsafe.__file__)"
Then look at the traceback from the error. It'll show you which file is trying the import. Common suspects: jinja2/utils.py, flask/templating.py.
pip list --format=columns | findstr jinja
On Linux/Mac:
pip list --format=columns | grep jinja
pip install pipdeptree
pipdeptree -p jinja2
This shows every package that depends on Jinja2 and what version they require. If you see something like your-old-package==1.2.3 requiring jinja2<3.1, that's your problem.
I've seen this with databricks-connect 11.x. It pins Jinja2 to 3.0.x, which is the version that uses soft_unicode. Upgrading to databricks-connect 13.x solved it in that case.
What NOT to do
- Don't try to monkey-patch – Adding
markupsafe.soft_unicode = strseems clever but it'll break in subtle ways. I've seen it cause silent text encoding bugs. - Don't delete the entire environment – That's overkill. Just fix the one package.
- Don't use
--no-deps– That'll create more dependency hell.
Real-world scenario that triggers this
You just joined a team with an existing Python project. You run pip install -r requirements.txt on a fresh machine. The requirements file has flask==2.2.5 and jinja2==3.0.3. When pip resolves dependencies, it grabs markupsafe==2.1.0. Boom, error. That's exactly the combo I've seen in dozens of projects from 2022-2023.
Quick commands summary
| Fix | Command |
|---|---|
| Quick pin | pip install markupsafe==2.0.1 |
| Upgrade core | pip install --upgrade flask jinja2 |
| Trace dependencies | pipdeptree -p jinja2 |
Start with fix 1. If you're short on time, that's your friend. If you want it fixed for good, go with fix 2 or 3. Either way, you'll be back to coding in minutes.