FastAPI集成aiogram时FSM(有限状态机)无法正常运行的问题及解决方案
Form.name.set() Problem
I adapted the aiogram FSM example from long polling to FastAPI webhook mode, but when sending the /start command to the bot, the backend throws this error:
AttributeError: 'NoneType' object has no attribute 'current_state'
The error hits at the await Form.name.set() line in the cmd_start handler. The code works perfectly with long polling, but breaks when using FastAPI to process updates manually.
Root Cause
In long polling mode, aiogram's Dispatcher automatically binds itself to the async task context for each incoming update. This lets Form.name.set() successfully retrieve the active dispatcher via Dispatcher.get_current().
But when processing updates manually through FastAPI (by calling dp.process_update(update)), the dispatcher's context isn't automatically bound to the current task. So Dispatcher.get_current() returns None, leading to the error when trying to call current_state().
Solution
Instead of using the state class's set() method directly, use the injected FSMContext object to manage the state. Here's the corrected cmd_start handler:
@dp.message_handler(commands='start', state="*") async def cmd_start(message: types.Message, state: FSMContext): """ Conversation's entry point """ # Set state via FSMContext instead of Form.name.set() await state.set_state(Form.name) await message.reply("Hi there! What's your name?")
Explanation
- Injecting
FSMContextgives you a session-specific context instance that works reliably in webhook mode, as it's tied directly to the user's conversation. - The
state="*"decorator ensures this handler can trigger regardless of the user's current state, which makes sense for a/startcommand that initiates a new flow. - For subsequent state transitions, stick to using the
FSMContextmethods (likeawait state.set_state(Form.next())if needed) instead of relying on the state class's methods—this avoids any context-related issues in webhook setups.
This fix ensures state management works as expected when processing updates manually through FastAPI, by cutting out the implicit dispatcher context dependency that only works in long polling.
内容的提问来源于stack exchange,提问作者oleh

