Duplicate Check
Describe the bug
In Flet 0.81.0 web mode (server-side, Docker), all Service controls (FilePicker, UrlLauncher) fail to work. page.launch_url() is also deprecated and delegates to UrlLauncher internally. There is no working way to open a native file dialog or launch a URL from a Flet web app in 0.81.0.
Two distinct failure modes depending on how/when the control is registered:
Mode A — "Unknown control: FilePicker" (red error bar across all views)
Occurs when FilePicker is added to page.overlay before or during the first page.update() — e.g., in main(), MainLayout, or app.py. The JS client doesn't recognize the control because the control tree handshake hasn't completed yet.
Mode B — TimeoutException after 10s: Timeout waiting for invoke method listener
Occurs when FilePicker is created per-click (inside the button handler), added to page.overlay, page.update() called, then await picker.pick_files() called. The JS listener for FilePicker never registers in time.
Environment
Python: 3.12.13 (CPython, Linux/Docker WSL2)
Flet: 0.81.0
Platform: Web mode (flet.app with server-side rendering, accessed via browser)
Docker: auditor_familiar_app container
OS host: Windows 11 + WSL2
Reproduction (minimal)
import flet as ft
async def main(page: ft.Page):
async def pick_file(_):
picker = ft.FilePicker()
page.overlay.append(picker)
page.update()
# Fails with TimeoutException after 10s in web mode:
result = await picker.pick_files(with_data=True)
print(result)
page.add(ft.ElevatedButton("Pick file", on_click=pick_file))
ft.app(main, port=8550)
All registration strategies attempted (all fail in web mode)
| Strategy |
Result |
FilePicker global in shared state |
Breaks multi-session (shared across users) |
FilePicker in MainLayout.did_mount() |
"Unknown control" on every view |
FilePicker per-click with overlay.append() + update() |
TimeoutException after 10s |
FilePicker in main() before first navigate() |
"Unknown control" on login view |
page._file_picker dynamic attribute |
Object recreated on WebSocket reconnect |
Per-click with asyncio.sleep(0.3) before pick_files() |
TimeoutException — sleep not enough |
ft.UrlLauncher().launch_url(url) |
Same problem — Service needs page registration |
page.launch_url(url) |
Deprecated, delegates to UrlLauncher internally |
Diagnostic output (check_flet.py --compat inside Docker)
FilePicker
[OK] ft.FilePicker exists
[OK] pick_files() is ASYNC
[OK] with_data=True available
[OK] FilePicker.upload() exists
URL Launcher
[OK] ft.UrlLauncher exists (Service — needs overlay)
[!!] page.launch_url() is DEPRECATED — source says "Use UrlLauncher() instead"
Page JavaScript
[!!] page has no JavaScript methods (run_javascript / eval_javascript)
Confirmed via inspect.getsource(ft.Page.launch_url):
@deprecated("Use UrlLauncher().launch_url() instead.", version="0.90.0", ...)
async def launch_url(self, url, ...):
Root cause hypothesis
Service controls (FilePicker, UrlLauncher) require a JS-side listener to be registered via the WebSocket handshake. In web mode with server-side rendering, this handshake does not complete reliably — the Python server calls invoke_method before the JS client has registered the listener for that specific control instance. The timeout is 10 seconds, which is never enough.
In desktop mode this works because the Flutter engine is local and the listener registration is synchronous/immediate.
Workaround implemented
We replaced FilePicker entirely with a separate FastAPI microservice that serves a native HTML <input type="file"> form. The Flet app shows the form URL in a copyable TextField, and the user opens it manually in a new browser tab. After uploading, the user clicks a "Done" button in Flet that triggers polling to retrieve the OCR result.
This works but is clearly not acceptable UX for a production app.
Expected behavior
ft.FilePicker (and ft.UrlLauncher) should work in Flet web mode (server-side) the same way they work in desktop mode. The JS listener registration should complete before pick_files() / launch_url() is awaited.
Suggestions
- Add a
await picker.ensure_ready() or similar method that waits for the JS listener to register before calling pick_files().
- Or expose
page.run_javascript() / page.eval_javascript() to allow workarounds at the app level.
- Or document clearly which controls do NOT work in web mode and provide the recommended alternative.
Additional details
page.run_javascript() / page.eval_javascript() do not exist on ft.Page in 0.81.0, so there is no way to work around this at the app level even with custom JS.
- The deprecation warning on
page.launch_url() pointing to 0.90.0 suggests this is a known area of change — any ETA on when UrlLauncher will work reliably in web mode?
Duplicate Check
Describe the bug
In Flet 0.81.0 web mode (server-side, Docker), all
Servicecontrols (FilePicker,UrlLauncher) fail to work.page.launch_url()is also deprecated and delegates toUrlLauncherinternally. There is no working way to open a native file dialog or launch a URL from a Flet web app in 0.81.0.Two distinct failure modes depending on how/when the control is registered:
Mode A — "Unknown control: FilePicker" (red error bar across all views)
Occurs when
FilePickeris added topage.overlaybefore or during the firstpage.update()— e.g., inmain(),MainLayout, orapp.py. The JS client doesn't recognize the control because the control tree handshake hasn't completed yet.Mode B —
TimeoutException after 10s: Timeout waiting for invoke method listenerOccurs when
FilePickeris created per-click (inside the button handler), added topage.overlay,page.update()called, thenawait picker.pick_files()called. The JS listener forFilePickernever registers in time.Environment
Reproduction (minimal)
All registration strategies attempted (all fail in web mode)
FilePickerglobal in shared stateFilePickerinMainLayout.did_mount()FilePickerper-click withoverlay.append()+update()TimeoutException after 10sFilePickerinmain()before firstnavigate()page._file_pickerdynamic attributeasyncio.sleep(0.3)beforepick_files()TimeoutException— sleep not enoughft.UrlLauncher().launch_url(url)page.launch_url(url)UrlLauncherinternallyDiagnostic output (
check_flet.py --compatinside Docker)Confirmed via
inspect.getsource(ft.Page.launch_url):Root cause hypothesis
Servicecontrols (FilePicker,UrlLauncher) require a JS-side listener to be registered via the WebSocket handshake. In web mode with server-side rendering, this handshake does not complete reliably — the Python server callsinvoke_methodbefore the JS client has registered the listener for that specific control instance. The timeout is 10 seconds, which is never enough.In desktop mode this works because the Flutter engine is local and the listener registration is synchronous/immediate.
Workaround implemented
We replaced
FilePickerentirely with a separate FastAPI microservice that serves a native HTML<input type="file">form. The Flet app shows the form URL in a copyableTextField, and the user opens it manually in a new browser tab. After uploading, the user clicks a "Done" button in Flet that triggers polling to retrieve the OCR result.This works but is clearly not acceptable UX for a production app.
Expected behavior
ft.FilePicker(andft.UrlLauncher) should work in Flet web mode (server-side) the same way they work in desktop mode. The JS listener registration should complete beforepick_files()/launch_url()is awaited.Suggestions
await picker.ensure_ready()or similar method that waits for the JS listener to register before callingpick_files().page.run_javascript()/page.eval_javascript()to allow workarounds at the app level.Additional details
page.run_javascript()/page.eval_javascript()do not exist onft.Pagein 0.81.0, so there is no way to work around this at the app level even with custom JS.page.launch_url()pointing to0.90.0suggests this is a known area of change — any ETA on whenUrlLauncherwill work reliably in web mode?