File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 148, in TemplateResponse
template = self.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 115, in get_template
return self.env.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/environment.py", line 964, in _load_template
template = self.cache.get(cache_key)
File "/opt/venv/lib/python3.14/site-packages/jinja2/utils.py", line 515, in getitem
rv = self._mapping[key]
TypeError: cannot use 'tuple' as a dict key (unhashable type: 'dict')
Error 2 — After patching Jinja2 cache (templates.env.cache = None), reveals underlying Starlette 1.0.0 API break
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 148, in TemplateResponse
template = self.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 115, in get_template
return self.env.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/environment.py", line 975, in _load_template
template = self.loader.load(self, name, self.make_globals(globals))
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 126, in load
source, filename, uptodate = self.get_source(environment, name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 197, in get_source
pieces = split_template_path(template)
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 30, in split_template_path
for piece in template.split("/"):
AttributeError: 'dict' object has no attribute 'split'
Root cause
Starlette 1.0.0 changed the TemplateResponse signature.
The codebase uses the old positional argument order throughout app.py, causing the context dict to be passed as the template name argument. The Jinja2 cache error in Python 3.14 masks this underlying issue until the cache is disabled.
Affected file
src/meshcore_hub/web/app.py — all TemplateResponse calls need updating to the new Starlette 1.0.0 signature.
Fresh install on Raspberry Pi 5 (ARM64), Raspberry Pi OS Bookworm 64-bit. Running the quickstart docker compose setup.
### Environment
- Python 3.14 (inside container)
- Starlette 1.0.0 (inside container)
- Docker on Raspberry Pi 5, ARM64
- meshcore-hub `latest` tag
### Steps to reproduce
1. Clone repo
2. Copy `.env.example` to `.env`, set `SERIAL_PORT`, `TZ`, `WEB_DATETIME_LOCALE`
3. `docker compose --profile migrate run --rm db-migrate`
4. `docker compose --profile mqtt --profile core --profile receiver up -d`
5. Browse to `http://[host]:8080`
### Result
`500 Internal Server Error` on every page request. Dashboard completely unusable out of the box.
### Error 1 — Python 3.14 + Jinja2 LRU cache incompatibility
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 148, in TemplateResponse
template = self.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 115, in get_template
return self.env.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/environment.py", line 964, in _load_template
template = self.cache.get(cache_key)
File "/opt/venv/lib/python3.14/site-packages/jinja2/utils.py", line 515, in getitem
rv = self._mapping[key]
TypeError: cannot use 'tuple' as a dict key (unhashable type: 'dict')
### Error 2 — After patching Jinja2 cache (`templates.env.cache = None`), reveals underlying Starlette 1.0.0 API break
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 148, in TemplateResponse
template = self.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 115, in get_template
return self.env.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/environment.py", line 975, in _load_template
template = self.loader.load(self, name, self.make_globals(globals))
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 126, in load
source, filename, uptodate = self.get_source(environment, name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 197, in get_source
pieces = split_template_path(template)
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 30, in split_template_path
for piece in template.split("/"):
AttributeError: 'dict' object has no attribute 'split'
### Root cause
Starlette 1.0.0 changed the `TemplateResponse` signature.
Old API (pre-1.0):
```python
TemplateResponse("template.html", {"request": request, "key": "value"})
```
New API (Starlette 1.0.0+):
```python
TemplateResponse(request, "template.html", {"key": "value"})
```
The codebase uses the old positional argument order throughout `app.py`, causing the context dict to be passed as the template name argument. The Jinja2 cache error in Python 3.14 masks this underlying issue until the cache is disabled.
### Affected file
`src/meshcore_hub/web/app.py` — all `TemplateResponse` calls need updating to the new Starlette 1.0.0 signature.
<!-- github-sync-id:4271804731 -->
Thanks for this. This has been fixed in an upcoming release, which is a major one.
We are replacing our proprietary receiver service to support LetsMesh Observers.
It is quite a substantial release and does require some upgrades and migrations. Unfortunately this does take a bit of effort for admins of the application.
If you want, I could backport this Starlette fix if you are unable to commit to upgrading. If you are just starting out, I suggest waiting for the new release.
Thanks for this. This has been fixed in an upcoming release, which is a major one.
We are replacing our proprietary receiver service to support LetsMesh Observers.
It is quite a substantial release and does require some upgrades and migrations. Unfortunately this does take a bit of effort for admins of the application.
https://github.com/ipnet-mesh/meshcore-hub/blob/feat/meshcore-packet-capture-receiver/docs/upgrading.md#v090
If you want, I could backport this Starlette fix if you are unable to commit to upgrading. If you are just starting out, I suggest waiting for the new release.
<!-- github-comment-id:4263004521 -->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fresh install on Raspberry Pi 5 (ARM64), Raspberry Pi OS Bookworm 64-bit. Running the quickstart docker compose setup.
Environment
latesttagSteps to reproduce
.env.exampleto.env, setSERIAL_PORT,TZ,WEB_DATETIME_LOCALEdocker compose --profile migrate run --rm db-migratedocker compose --profile mqtt --profile core --profile receiver up -dhttp://[host]:8080Result
500 Internal Server Erroron every page request. Dashboard completely unusable out of the box.Error 1 — Python 3.14 + Jinja2 LRU cache incompatibility
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 148, in TemplateResponse
template = self.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 115, in get_template
return self.env.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/environment.py", line 964, in _load_template
template = self.cache.get(cache_key)
File "/opt/venv/lib/python3.14/site-packages/jinja2/utils.py", line 515, in getitem
rv = self._mapping[key]
TypeError: cannot use 'tuple' as a dict key (unhashable type: 'dict')
Error 2 — After patching Jinja2 cache (
templates.env.cache = None), reveals underlying Starlette 1.0.0 API breakFile "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 148, in TemplateResponse
template = self.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/starlette/templating.py", line 115, in get_template
return self.env.get_template(name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/environment.py", line 975, in _load_template
template = self.loader.load(self, name, self.make_globals(globals))
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 126, in load
source, filename, uptodate = self.get_source(environment, name)
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 197, in get_source
pieces = split_template_path(template)
File "/opt/venv/lib/python3.14/site-packages/jinja2/loaders.py", line 30, in split_template_path
for piece in template.split("/"):
AttributeError: 'dict' object has no attribute 'split'
Root cause
Starlette 1.0.0 changed the
TemplateResponsesignature.Old API (pre-1.0):
New API (Starlette 1.0.0+):
The codebase uses the old positional argument order throughout
app.py, causing the context dict to be passed as the template name argument. The Jinja2 cache error in Python 3.14 masks this underlying issue until the cache is disabled.Affected file
src/meshcore_hub/web/app.py— allTemplateResponsecalls need updating to the new Starlette 1.0.0 signature.Thanks for this. This has been fixed in an upcoming release, which is a major one.
We are replacing our proprietary receiver service to support LetsMesh Observers.
It is quite a substantial release and does require some upgrades and migrations. Unfortunately this does take a bit of effort for admins of the application.
https://github.com/ipnet-mesh/meshcore-hub/blob/feat/meshcore-packet-capture-receiver/docs/upgrading.md#v090
If you want, I could backport this Starlette fix if you are unable to commit to upgrading. If you are just starting out, I suggest waiting for the new release.
This fix has now been merged. This issue should be fixed now.