Troubleshooting Guide¶
Common issues and solutions for aiogram-sentinel.
Quick Help: For common questions, see the FAQ. For step-by-step guides, see the Tutorials.
Quick Diagnosis¶
Check Bot Status¶
@dp.message(Command("status"))
async def bot_status(message: Message):
"""Check bot and middleware status."""
status = {
"bot_running": True,
"middleware_registered": hasattr(dp.message, 'middleware'),
"storage_connected": await check_storage_connection(),
}
await message.answer(f"Bot Status: {status}")
Enable Debug Logging¶
import logging
# Enable debug logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
Policy Registry Issues¶
Policy Not Found Errors¶
Symptoms: ValueError: Policy 'policy_name' not found
Solutions:
-
Check policy registration:
-
Verify policy name spelling:
-
Register policy before use:
Policy Skipped Due to Missing Scope Identifiers¶
Symptoms: Policy not applied, debug log shows "Policy skipped: required scope identifiers missing"
Solutions:
-
Check scope cap requirements:
from aiogram_sentinel import resolve_scope, Scope # Test scope resolution user_id = 123 chat_id = 456 cap = Scope.USER resolved = resolve_scope(user_id, chat_id, cap) if resolved is None: print(f"Cannot satisfy scope cap {cap} with user_id={user_id}, chat_id={chat_id}") else: print(f"Resolved scope: {resolved}")
-
Adjust scope cap or ensure identifiers are available:
-
Debug scope resolution:
Deprecation Warnings for Old Decorators¶
Symptoms: DeprecationWarning: @rate_limit is deprecated
Solutions:
-
Migrate to policy registry:
# Before (deprecated) @rate_limit(5, 60, scope="user") @debounce(2, scope="chat") async def handler(message): await message.answer("Hello!") # After (recommended) from aiogram_sentinel import registry, policy, Policy, ThrottleCfg, DebounceCfg, Scope # Register policies once registry.register(Policy("user_throttle", "throttle", ThrottleCfg(rate=5, per=60, scope=Scope.USER))) registry.register(Policy("chat_debounce", "debounce", DebounceCfg(window=2, scope=Scope.CHAT))) # Use policies @policy("user_throttle", "chat_debounce") async def handler(message): await message.answer("Hello!")
-
Suppress warnings temporarily:
Policy Resolution Conflicts¶
Symptoms: Warning about both @policy and legacy decorators found
Solutions:
-
Remove legacy decorators:
# Problem: Both policy and legacy decorator @policy("user_throttle") @rate_limit(5, 60) # This will be ignored with warning async def handler(message): await message.answer("Hello!") # Solution: Remove legacy decorator @policy("user_throttle") async def handler(message): await message.answer("Hello!")
-
Use only legacy decorators (temporary):
Policy Configuration Validation Errors¶
Symptoms: ValueError: rate must be positive
or similar validation errors
Solutions:
-
Check configuration values:
from aiogram_sentinel import ThrottleCfg, DebounceCfg # Valid configurations throttle_cfg = ThrottleCfg(rate=5, per=60) # rate > 0, per > 0 debounce_cfg = DebounceCfg(window=2) # window > 0 # Invalid configurations will raise ValueError try: invalid_cfg = ThrottleCfg(rate=0, per=60) # rate must be > 0 except ValueError as e: print(f"Configuration error: {e}")
-
Validate before registration:
Key Generation Issues¶
Debugging Generated Keys¶
Symptoms: Keys not working as expected, rate limiting not functioning correctly
Solutions:
-
Enable key debugging:
-
Print generated keys:
-
Verify key format:
Key Validation Errors¶
Symptoms: ValueError
when creating keys
Common Causes: - Empty namespace or identifiers - Separator characters in identifiers - Invalid scope usage
Solutions:
-
Check namespace:
-
Check identifiers:
-
Check scope usage:
Context Extraction Issues¶
Symptoms: Wrong user/chat IDs extracted from events
Solutions:
-
Debug context extraction:
-
Check event attributes:
-
Handle missing context:
# Check if context is available user_id, chat_id = extract_group_ids(event, data) if user_id and chat_id: # Use GROUP scope key = kb.group("throttle", user_id, chat_id) elif user_id: # Use USER scope key = kb.user("throttle", user_id) elif chat_id: # Use CHAT scope key = kb.chat("throttle", chat_id) else: # Use GLOBAL scope key = kb.global_("throttle")
Deprecation Warnings¶
Symptoms: Deprecation warnings for rate_key()
and debounce_key()
Solutions:
-
Update to KeyBuilder:
-
Suppress warnings temporarily:
Key Collision Detection¶
Symptoms: Different inputs producing same keys
Solutions:
-
Test key uniqueness:
-
Verify key components:
# Test different namespaces key1 = kb.user("throttle", 123) key2 = kb.user("debounce", 123) assert key1 != key2, "Keys should be different for different namespaces" # Test different scopes key3 = kb.user("throttle", 123) key4 = kb.chat("throttle", 123) assert key3 != key4, "Keys should be different for different scopes"
Performance Issues¶
Symptoms: Slow key generation or high memory usage
Solutions:
-
Reuse KeyBuilder instances:
-
Cache frequently used keys:
Common Issues¶
Bot Not Responding¶
Symptoms: Bot doesn't respond to messages
Possible Causes: - Bot token invalid or expired - Middleware not registered - Network connectivity issues - Bot blocked by user
Solutions:
-
Check bot token:
-
Verify middleware registration:
-
Test basic functionality:
Rate Limiting Issues¶
Symptoms: Users get blocked unexpectedly or rate limiting doesn't work
Possible Causes: - Configuration too strict - Time zone issues - Storage backend problems - Handler-specific overrides
Solutions:
-
Check current configuration:
-
Adjust rate limits:
-
Check handler-specific settings:
Redis Connection Issues¶
Symptoms: Redis connection errors, storage not working
Possible Causes: - Redis server not running - Wrong connection URL - Authentication issues - Network problems
Solutions:
-
Check Redis server:
-
Verify connection URL:
-
Check Redis configuration:
Debouncing Issues¶
Symptoms: Messages are debounced when they shouldn't be, or debouncing doesn't work
Possible Causes: - Debounce window too long - Key generation issues - Storage backend problems
Solutions:
-
Check debounce configuration:
-
Test debounce functionality:
-
Check key generation:
Performance Issues¶
High Memory Usage¶
Symptoms: Bot consumes too much memory
Solutions:
-
Use Redis storage:
-
Configure cleanup:
-
Monitor memory usage:
Slow Response Times¶
Symptoms: Bot responds slowly to messages
Solutions:
-
Optimize storage backend:
-
Reduce middleware complexity:
-
Monitor performance:
Error Messages¶
ConfigurationError¶
Message: "throttling_default_max must be positive"
Solution: Ensure all numeric configuration values are positive:
config = SentinelConfig(
throttling_default_max=5, # Must be > 0
throttling_default_per_seconds=60, # Must be > 0
)
StorageError¶
Message: "Storage operation failed"
Solution: Check storage backend connection and configuration:
# Test storage connection
try:
# Test with a simple operation
await infra.rate_limiter.allow("test", 1, 1)
print("Storage connection successful")
except Exception as e:
print(f"Storage error: {e}")
ImportError¶
Message: "No module named 'aiogram_sentinel'"
Solution: Install aiogram-sentinel:
Debugging Tools¶
Enable Verbose Logging¶
import logging
# Configure detailed logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('bot.log'),
logging.StreamHandler()
]
)
Health Check Endpoint¶
@dp.message(Command("health"))
async def health_check(message: Message):
"""Comprehensive health check."""
health = {
"bot": "healthy",
"middleware": "registered",
"storage": await check_storage_health(),
"rate_limiter": await check_rate_limiter_health(),
"debounce": await check_debounce_health(),
}
await message.answer(f"Health Status: {health}")
async def check_storage_health():
try:
# Test with a simple operation
await infra.rate_limiter.allow("health_check", 1, 1)
return "healthy"
except Exception:
return "unhealthy"
Performance Monitoring¶
import time
from functools import wraps
def monitor_performance(func):
@wraps(func)
async def wrapper(*args, **kwargs):
start_time = time.time()
result = await func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {end_time - start_time:.3f} seconds")
return result
return wrapper
@monitor_performance
@dp.message()
async def monitored_handler(message: Message):
await message.answer("Response")
Getting Help¶
Before Asking for Help¶
- Check this troubleshooting guide
- Enable debug logging
- Test with minimal configuration
- Check aiogram-sentinel version
- Verify Python and aiogram versions
Provide Information¶
When reporting issues, include:
- aiogram-sentinel version:
pip show aiogram-sentinel
- Python version:
python --version
- aiogram version:
pip show aiogram
- Error messages: Full traceback
- Configuration: Your SentinelConfig settings
- Storage backend: Memory or Redis
- Environment: OS, Python version, etc.
Community Support¶
- GitHub Issues: Report bugs and request features
- Discussions: Ask questions and share ideas
- Documentation: Read the full documentation