aiogram
aiogram copied to clipboard
FSM Context States are not working when forwarding multiple answers at once
Checklist
- [X] I am sure the error is coming from aiogram code
- [X] I have searched in the issue tracker for similar bug reports, including closed ones
Context
like i said in the title when you forward multiple messages at once to complete multiple states it stuck in the first state
Imagine we have 3 States()
.
first_name, last_name, age
when you send /start to the bot, the bot asks you to send your first_name
and when you gave the answer it asks for your last_name
and when you answered that too it askes for your age
now imagine you started the bot and then forwarded your first_name, last_name, age
at once
the bot should take each message for each state
but it takes all of those answers (first_name, last_name, age
) as first_name
and asks for your last name 3 times.
Expected behavior
The bot should take each message for each state
Current behavior
the bot take the first message and get stucked at that state and The bot accept the first message as
Steps to reproduce
well unfortunately i dont know how to fix it
Code example
import asyncio
import logging
from aiogram import Bot, Router, Dispatcher
from aiogram.dispatcher.fsm.context import FSMContext
from aiogram.dispatcher.fsm.state import StatesGroup, State
from aiogram.types import Message
bot = Bot('token')
router = Router()
class States(StatesGroup):
first_name = State()
last_name = State()
age = State()
@router.message(commands=['start'])
async def start(message: Message, state: FSMContext):
await message.answer('send your first name')
await state.set_state(States.first_name)
@router.message(state=States.first_name)
async def first_name(message: Message, state: FSMContext):
await message.answer("send your last name")
await state.update_data(first_name=message.text)
await state.set_state(States.last_name)
@router.message(state=States.last_name)
async def last_name(message: Message, state: FSMContext):
await message.answer("send your age")
await state.update_data(last_name=message.text)
await state.set_state(States.age)
@router.message(state=States.age)
async def age(message: Message, state: FSMContext):
await state.update_data(age=message.text)
await state.clear()
await message.answer("done :check:")
async def main() -> None:
logging.basicConfig(filename='logs.log', filemode='w', level=logging.DEBUG,
format="%(asctime)s %(name)-30s %(levelname)-8s %(message)s",
datefmt='%Y-%m-%d %H:%M:%S')
dp = Dispatcher()
dp.include_router(router)
await dp.start_polling(bot, allowed_updates=["message"])
if __name__ == "__main__":
print("started")
asyncio.run(main())
Logs
No response
Additional information
i tested it in private chats and supergroups and the problem was there
You're working with async application. It's not protected from conditions race by default.
While your code is awaiting for set_state
operation, aiogram starts processing the next update.
This is default asyncio
behaviour.
If you wanna change this behaviour - create middleware that locks processing for every user.
Maybe we should add a built-in optional flag for sequential processing of updates? /cc @JrooTJunior
Flag may add performance issues. Per-user locking middleware is enough
Use events isolation mode in v3