Repository navigation
Troubleshooting
oldmangan edited this page Oct 10, 2026
·
4 revisions
| Symptom | Cause and fix |
|---|---|
| HTTP 422 opening the app | No entrypoint found. Add APP_ENTRYPOINT = "ClassName", or name the class after the module. |
| Page loads but no widgets appear | No wapyt wheel in the modules folder, or a stale one. Re-run scripts/dev_wheel.sh <modules folder> and restart the service. |
No widgetset found with from wapyt import ...
|
wapyt is installed editable server-side (pyTincture ≤ 1.0.0rc12 cannot see it). Add widget.py and import widget, or install wapyt non-editable. |
| UI renders twice |
__init__ calls load_ui() and so does the metaclass. Delete the __init__. |
assets failed to load component 'X' |
The wheel's JS did not register. Rebuild the wheel; check the browser console for a hash-verification error. |
Widget asset integrity check failed: wapyt/assets/… and the app never starts |
An asset changed without the manifest being regenerated. Run python3 scripts/generate_assets_manifest.py ., commit wapyt/pytincture-assets.json, rebuild the wheel (Development). CI's --check catches it on a pull request; a branch built before CI runs doesn't. |
| A MediaPlayer stream fetches but never plays | The page's CSP lacks media-src 'self' blob: (hls.js plays through blob: URLs); the player's status line names the directive. See MediaPlayer. |
| A MediaPlayer stream from another server never loads (no error from the server) | The page's CSP: hls.js fetches with XHR, so the media server's origin must be in connect-src as well as media-src. See connecting your media server. |
| A protected stream plays when it shouldn't (or someone else's does) | Its responses are cacheable: send Cache-Control: no-store (or private) and Vary: Authorization on access-controlled media. |
| A MediaPlayer item sits on "Loading…" | It has no src and nothing answered resolve: bind on_resolve before load (items given to the constructor are resolved during construction). |
CellConfig(width=...) seems ignored |
Use "100%" to fill, "auto" for content size, "220px" for fixed. |
| Modal buttons clipped |
ModalConfig(height=...) is honest; body content scrolls inside it. Make it taller. |
| Hidden modals pile up |
hide() keeps the overlay. Use dispose_on_close=True and close() for per-use dialogs. |
| A form vanished from a modal |
set_content() replaces the body. Mount with container=modal.body. |
A body font rule does nothing |
Layouts and modals read --wapyt-font-family; set it on :root. |
| Button labels overlap; icons show as words | A ligature icon font. Use MDI classes and remove the font <link>. |
if el is None: never fires on a DOM lookup |
js.document.getElementById(...) returns JS null as JsNull, not None. Test truthiness. (wapyt widget payloads and getters already give real None.) |
| An async handler fails silently |
ensure_future swallows exceptions. Wrap the coroutine (see Events and Async). |
| BFF data written in one call is gone in the next | State in BFF module globals; the module re-executes per call. |
| Chat history lost on reload |
ChatConfig(storage_key=...) unset. |
| A streamed reply renders empty | The backend sent an in-band {"error": ...} chunk. Use Chat.consume_stream. |
A file picker raises SecurityError
|
It ran after an await. Call it first in the click handler. |
| Mic button does nothing | Set PYTINCTURE_ALLOW_MICROPHONE=1 and use a secure context (http://127.0.0.1, not a LAN IP). |
| Terminal is a few columns wide in a tab | It was created hidden. Call terminal.fit() when its tab becomes active. |
| Terminal never loads | xterm files are not served under asset_base (default /xterm). |
wapyt is MIT-licensed · Repository · pyTincture · Issues
Getting started
Widgets
- Layout and MainWindow
- Tree
- DataTable
- Form
- ModalWindow
- Window
- TabWidget
- Toolbar
- Sidebar
- Chat
- Terminal
- CardPanel
- ResourceBoard
- File Transfer
- Message
- ContextMenu
- MenuBar
- Listbox
- Kanban
- ProgressBar
- Pagination
- Popup and tooltips
- Chart
- Scheduler
- MediaPlayer
Guides
Planning
Contributing