zauberzeug / nicegui

Create web-based user interfaces with Python. The nice way.
https://nicegui.io
MIT License
8.14k stars 492 forks source link

RuntimeError: app.storage.user needs a storage_secret passed in ui.run() #3273

Open bin-san opened 1 week ago

bin-san commented 1 week ago

Description

Though I have ui.run(host=host, port=port, show=False, storage_secret='bin-san-2002', favicon='🎉')

python-and-fiction commented 1 week ago

Need more details, I can't reproduce it.

bin-san commented 1 week ago

Steps to reproduce:

  1. get the code at: https://gist.github.com/bin-san/ede5d876aba43eff290a776915659345

  2. run the file

  3. open webpage localhost:8999 to see Screenshot from 2024-06-24 16-33-56

  4. Click the floating action button on the bottom right Screenshot from 2024-06-24 16-34-21

  5. Click the create fab-action Screenshot from 2024-06-24 16-34-51

  6. Enter some dummy string Screenshot from 2024-06-24 16-35-00

  7. Click on the indigo color arrow button of the newly created card -> Screenshot from 2024-06-24 16-35-27

  8. Now check your log:

    NiceGUI ready to go on http://localhost:8999, http://172.17.0.1:8999, and http://192.168.1.2:8999 app.storage.user needs a storage_secret passed in ui.run() Traceback (most recent call last): File "/home/point/PycharmProjects/PartyRooms/.venv/lib/python3.12/site-packages/nicegui/background_tasks.py", line 52, in _handle_task_result task.result() File "/home/point/PycharmProjects/PartyRooms/.venv/lib/python3.12/site-packages/nicegui/binding.py", line 39, in refresh_loop _refresh_step() File "/home/point/PycharmProjects/PartyRooms/.venv/lib/python3.12/site-packages/nicegui/binding.py", line 49, in _refresh_step value = transform(_get_attribute(source_obj, source_name)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/point/PycharmProjects/PartyRooms/main.py", line 444, in monitor_cmd if not app.storage.user.get('last-command'): ^^^^^^^^^^^^^^^^ File "/home/point/PycharmProjects/PartyRooms/.venv/lib/python3.12/site-packages/nicegui/storage.py", line 143, in user raise RuntimeError('app.storage.user needs a storage_secret passed in ui.run()') RuntimeError: app.storage.user needs a storage_secret passed in ui.run()

falkoschindler commented 1 week ago

Hi @bin-san, this does indeed look like a bug. At least the error message doesn't make too much sense if the storage_secret is given in ui.run.

In order to help narrowing down this bug and to compare it to #2520: Could you, please, try to extract a minimum reproducible code example? Thanks! Why is it important to provide a minimal reproducible example?

bin-san commented 1 week ago

Yes sir. I am trying to write the minimum reproducible code.

bin-san commented 1 week ago
from nicegui import ui, app

@ui.page('/')
def index():
    app.storage.user['name'] = 'San'
    def f(v):
        ui.notify(app.storage.user.get('name'))
        return v
    ui.label().bind_text_from(app.storage.user, 'name', backward=f)

ui.run(show=False, storage_secret='bin-san-2002')

The problem is that the function given in backward function can not access user storage.

falkoschindler commented 1 week ago

Thanks a lot, @bin-san! This is very helpful.

Actually, there's another error happening because the backward function has no current UI context:

The current slot cannot be determined because the slot stack for this task is empty.
This may happen if you try to create UI from a background task.
To fix this, enter the target slot explicitly using `with container_element:`.

But even after fixing this problem by explicitly using the current client, the warning about a missing storage_secret remains:

@ui.page('/')
def index():
    app.storage.user['name'] = 'San'
    client = ui.context.client

    def f(v):
        with client:
            ui.notify(app.storage.user.get('name'))
        return v
    ui.label().bind_text_from(app.storage.user, 'name', backward=f)
python-and-fiction commented 6 days ago

I set a print in storage.py,And I found starlette.middleware.base._CachedRequest object becomes None during first visiting page. image 1719294409597 Then I look it up in starlette's repository,similar question is founded: RuntimeError("No response returned") in BaseHTTPMiddleware · Issue #2516 · encode/starlette https://github.com/encode/starlette/issues/2516 Maybe it is helpful.Or it is a direction for others who would solve this problem.

bin-san commented 6 days ago

@falkoschindler Hi. Same problem accessing app.storage.user from an app.websocket

from nicegui import ui, app
from fastapi import WebSocket
from uuid import uuid4
from time import time_ns
def uid():
    """Generates an unique id"""
    return f'{uuid4()}-{time_ns()}'

app.add_media_file(local_file='./sample.mp4', url_path='/video')

app.storage.general['octopus'] = {}

@app.websocket('/sync_video/{video_id}')
async def sync_video(websocket:WebSocket, video_id):
    with ui.context.client:
        if not app.storage.user.get('id'):
            app.storage.user['id'] = uid()
    await websocket.accept()
    while True:
        msg = await websocket.receive_text()
        await websocket.send_text(f'Got {msg}')

@ui.page('/{video_id}')
def index(video_id):
    ui.add_head_html(f'''
    <script defer>
    window.ws = new WebSocket('ws://{host}:{port}/sync_video/{video_id}')
    window.ws.onmessage = (event)=>{{
    window.display1.innerText = event.data
    }}
    </script>
    ''')
    ui.input('Enter a message').classes('w-full').props('id=input1')
    ui.button('Broadcast').on('click', js_handler='''
    (event)=>window.ws.send(input1.value)
    ''')
    ui.label().classes('w-full').props('id=display1')

host = 'localhost'
port = 8000

ui.run(host=host, port=port, show=False, storage_secret='bin-san')