Skip to content

bug: FilePicker and UrlLauncher Service controls fail in web mode (0.81.0) — TimeoutException or "Unknown control" #6250

@Ponce1969

Description

@Ponce1969

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

  1. Add a await picker.ensure_ready() or similar method that waits for the JS listener to register before calling pick_files().
  2. Or expose page.run_javascript() / page.eval_javascript() to allow workarounds at the app level.
  3. 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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions