The router loads the material row (starting a transaction) before calling material_service.update_material, which then opened its own async with db.begin() → SQLAlchemy 'A transaction is already begun on this Session' → INTERNAL_ERROR on every PATCH (incl. changing the reference unit from ضرایب تبدیل). Mutations now run inside the request transaction committed by the get_db dependency.