Skip to main content
Common issues with the PraisonAI Gateway daemon and server, with step-by-step troubleshooting guides.
from praisonaiagents import Agent

agent = Agent(
    name="Gateway Helper",
    instructions="Diagnose PraisonAI Gateway connectivity issues.",
)
agent.start("Gateway health check: is the daemon reachable?")
The user checks gateway status, reads logs, and restarts the daemon until channels respond again.

Common Issues

Port Already In Use / Two Gateways Running

Symptom: Gateway fails to start with a clear error message about port conflicts.
Error: Gateway port 8765 is already in use.

  Another gateway may be running (PID 8864).
  Stop it:  praisonai gateway stop
  Or use a different port:  GATEWAY_PORT=8766 praisonai gateway start

  Only ONE gateway process should poll each Telegram bot token.
1

Check PID lock and port status

praisonai gateway status
Look for lines like:
  • Gateway PID lock: Process 12345 running (127.0.0.1:8765)
  • Port 127.0.0.1:8765: In use
2

Stop the existing gateway gracefully

praisonai gateway stop
This sends SIGTERM and waits for graceful shutdown. The gateway drains active sessions for up to 10 seconds — in-flight turns and queued inbox messages are persisted before exit. Sessions that exceed the timeout are force-persisted with a SESSION_END event (had_pending_work, was_executing). Use --force to skip the drain. See Gateway Session Continuity.
3

If gateway is stuck, force stop

praisonai gateway stop --force
This sends SIGKILL directly (SIGTERM on Windows) for immediate termination.
4

If port is used by non-gateway process

# Find what's using the port
lsof -i :8765
# Linux alternative:
netstat -ano | findstr :8765

# Either kill that process or use a different port
GATEWAY_PORT=8766 praisonai gateway start
# Or:
praisonai gateway start --port 8766
5

Clean up stale lock file (if needed)

# Check the PID lock file
cat ~/.praisonai/gateway-127_0_0_1-8765.pid

# Remove stale lock manually (auto-cleaned on next start)
rm ~/.praisonai/gateway-127_0_0_1-8765.pid
Stale locks are automatically detected and removed, but you can clean them manually if needed.

Telegram Bot Goes Silent After Restart

Symptom: Gateway /health endpoint returns healthy, but Telegram messages aren’t received after a restart or crash. Cause: Two processes are polling the same Telegram bot token. Telegram delivers messages to only one poller, causing the bot to appear “silent” when the wrong process gets the messages.
1

Stop all gateway instances

praisonai gateway stop --force
This ensures all instances are terminated, even if PID files are corrupted.
2

Verify no processes are running

praisonai gateway status
Should show:
  • Gateway PID lock: No lock file found
  • Port 127.0.0.1:8765: Available
3

Start a single gateway instance

praisonai gateway start
Only start one instance to ensure exclusive bot token polling.
4

Test bot responsiveness

Send a message to your Telegram bot. It should respond normally now that only one process is polling the token.

Daemon Running But Gateway Unreachable

Symptom: praisonai gateway status shows Daemon service: Running (launchd) but Gateway not reachable at http://127.0.0.1:8765/health.
1

Verify daemon is actually running

praisonai gateway status --daemon-only
Look for Running status and process ID.
2

Check daemon logs for errors

praisonai gateway logs

# Or check raw log files:
# macOS: tail ~/.praisonai/logs/bot-stderr.log
# Linux: journalctl --user -u praisonai-bot
Look for Python tracebacks or port binding errors.
3

Check port and PID lock status

praisonai gateway status
This now reports both port usage and PID lock status directly. Look for:
  • Gateway PID lock: Process <pid> running or No lock file found
  • Port 127.0.0.1:8765: In use or Available
If another process is using the port, use praisonai gateway stop to stop an existing gateway, or choose a different port.
4

Verify PraisonAI version

praisonai --version
Upgrade to ≥ v4.6.23 if you see older versions - earlier versions had IndentationError bugs fixed in PR #1484.
5

Restart the daemon

# macOS
launchctl kickstart -k gui/$(id -u)/ai.praison.bot

# Linux  
systemctl --user restart praisonai-bot

# Or reinstall completely
praisonai onboard

Rapidly Growing Log Files

Symptom: ~/.praisonai/logs/bot-stderr.log grows to multiple MB per minute.
1

Check log file size

ls -lh ~/.praisonai/logs/bot-stderr.log
If growing rapidly (>1MB/min), this indicates a crash loop.
2

View recent errors

tail -50 ~/.praisonai/logs/bot-stderr.log
Look for repeated Python tracebacks, especially IndentationError.
3

Stop the daemon

# macOS
launchctl unload ~/Library/LaunchAgents/ai.praison.bot.plist

# Linux
systemctl --user stop praisonai-bot
4

Clear logs and restart

# Clear the log file
> ~/.praisonai/logs/bot-stderr.log

# Upgrade PraisonAI
pip install --upgrade praisonai

# Restart daemon
praisonai gateway install --start

Daemon Not Installed

Symptom: praisonai gateway status shows Daemon service: Not installed (systemd).
1

Run the onboarding wizard

praisonai onboard
This installs the daemon service for your platform.
2

Verify installation

praisonai gateway status --daemon-only
Should show Installed but not running or Running.
3

Start the service

# Manual start
praisonai gateway install --start

# Or check platform-specific commands
praisonai gateway status

HTTP 500 on Health Endpoint

Symptom: curl http://127.0.0.1:8765/health returns 500 Internal Server Error.
1

Check PraisonAI version

praisonai --version
Versions before v4.6.23 had AttributeError bugs in the health endpoint.
2

Upgrade PraisonAI

pip install --upgrade praisonai
3

Restart the gateway

praisonai gateway install --start
4

Test health endpoint

curl http://127.0.0.1:8765/health
Should return JSON with status, uptime, agents, sessions, clients, and channels.

Windows: ‘charmap’ codec error from Telegram bot replies

Symptom: Telegram users receive Error: 'charmap' codec can't encode character '⚠' in position N: character maps to <undefined> instead of the real error message. Root cause: Windows default console encoding is cp1252, not UTF-8. When agent exceptions contained warning symbols (⚠), emoji, or accented text, the error formatter crashed before the real error could be reported.
1

Verify your version contains the fix

python -c "from praisonai.gateway.unicode_utils import safe_error_message; print('OK')"
If this command runs without error, you have the fix from PR #1754.
2

Upgrade to a fixed version

pip install --upgrade praisonai
Upgrade to PraisonAI version that contains PR #1754 — Gateway and Telegram bot error handlers now sanitize exception text to ASCII-safe form for transport, while preserving full Unicode in logs.
3

Restart the gateway

praisonai gateway install --start
4

Test the fix

Users will now see clean error messages instead of charmap crashes:
  • Error: API quota exceeded. Check billing. (was: charmap crash hiding OpenAI 429)
  • Error: Rate limit exceeded. Try again later.
  • Error: Authentication failed. Check API key.
  • Error: Request timeout. Try again.
No workaround needed on supported versions. The previously recommended PYTHONUTF8=1 / PYTHONIOENCODING=utf-8 workaround is no longer required for the bot reply path (still useful for general console output).

Permission Denied Errors

Symptom: Daemon fails to start with permission errors in logs.
# Check LaunchAgent permissions
ls -la ~/Library/LaunchAgents/ai.praison.bot.plist

# Reload LaunchAgent
launchctl unload ~/Library/LaunchAgents/ai.praison.bot.plist
launchctl load ~/Library/LaunchAgents/ai.praison.bot.plist

Clean Reinstall Process

When all else fails, perform a clean reinstall:
1

Stop and uninstall

praisonai gateway uninstall
2

Clear configuration

# Backup first if needed
rm -rf ~/.praisonai/logs
rm -rf ~/.praisonai/config
3

Upgrade PraisonAI

pip install --upgrade praisonai
4

Run onboarding

praisonai onboard
Follow the wizard to reinstall the daemon service.
5

Verify installation

praisonai gateway status
Should show daemon running and gateway reachable.

Reading the hello_error Envelope

When the gateway rejects a connection, it sends a structured hello_error frame before closing. Each (code, next_step) pair maps to a specific operator action.
codenext_stepAction
rate_limitedwait_then_retryWait retry_after_seconds then reconnect; if persistent, raise the rate limiter ceiling
origin_not_alloweddo_not_retryAdd the client origin to allowed_origins in gateway.yaml
configuration_errordo_not_retryExternal bind without allowed_origins configured; bind to loopback or set the allowlist
auth_requiredreauthenticateFetch a token (CLI or pairing flow) and reconnect
protocol_unsupportedupgrade_clientUpdate the client SDK to a newer version
protocol_unsupporteddowngrade_clientServer is older than the client; pin the client to an older release or upgrade the server
agent_not_founddo_not_retryFix the agent_id in the hello frame
Example envelope received on rate-limit:
{
  "type": "hello_error",
  "code": "rate_limited",
  "message": "Too many connection attempts",
  "next_step": "wait_then_retry",
  "retry_after_seconds": 30,
  "next": "wait_then_retry"
}
See Gateway Handshake Protocol for the full field reference and ConnectRecoveryStep values.

Authentication Errors

GatewayStartupError: Cannot bind to 0.0.0.0 without an auth token

Symptom: Gateway fails to start when binding to external interfaces without authentication.
1

Use onboarding wizard

praisonai onboard
This automatically generates and saves a secure token.
2

Or set token manually

export GATEWAY_AUTH_TOKEN=$(openssl rand -hex 16)
praisonai gateway start --host 0.0.0.0

UIStartupError: Cannot bind to 0.0.0.0 with default admin/admin credentials

Symptom: Chainlit UI fails to start on external interface with default credentials.
1

Set custom credentials

export CHAINLIT_USERNAME=myuser
export CHAINLIT_PASSWORD=mypass
praisonai chat --host 0.0.0.0
2

Or allow defaults for demos (unsafe)

export PRAISONAI_ALLOW_DEFAULT_CREDS=1
praisonai chat --host 0.0.0.0

My gateway logs show gw_****xxxx instead of the full token

This is intentional for security — tokens are fingerprinted in logs to prevent exposure.
1

Retrieve full token from environment file

cat ~/.praisonai/.env | grep GATEWAY_AUTH_TOKEN
2

Or check environment variables

echo $GATEWAY_AUTH_TOKEN
Symptom: One auth method works but the other fails, even with the same token. Cause (pre-fix): HTTP/magic-link and WebSocket used different secret sources before PR #1744.
1

Upgrade PraisonAI

Upgrade to PraisonAI ≥ v4.6.47 (ships PR #1744). Config token now exports to env, unifying all auth paths.
2

Restart the gateway

praisonai gateway restart
Config token precedence is now enforced on restart.

Restart After Config Change

When you update bot configuration files, restart the daemon using these OS-specific commands (matching the onboard Done panel):
launchctl kickstart -k gui/$(id -u)/ai.praison.bot

Diagnostic Commands

Quick commands for gathering diagnostic information:
# Full status check
praisonai gateway status

# Daemon-only check (for scripts)
praisonai gateway status --daemon-only

# Recent logs (last 50 lines)
praisonai gateway logs -n 50

# Check the PID lock file
cat ~/.praisonai/gateway-127_0_0_1-8765.pid

# Stop a running gateway
praisonai gateway stop
praisonai gateway stop --force

# Check port usage
lsof -i :8765

# Test health endpoint directly
curl -v http://127.0.0.1:8765/health

# Check PraisonAI version
praisonai --version

# Platform daemon status
# macOS: launchctl list | grep ai.praison
# Linux: systemctl --user status praisonai-bot
# Windows: schtasks /Query /TN PraisonAIGateway

Platform-Specific Notes

LaunchAgent Path: ~/Library/LaunchAgents/ai.praison.bot.plist Log Path: ~/.praisonai/logs/bot-stderr.log
# Manual management
launchctl load ~/Library/LaunchAgents/ai.praison.bot.plist
launchctl unload ~/Library/LaunchAgents/ai.praison.bot.plist
launchctl kickstart -k gui/$(id -u)/ai.praison.bot

# Check if loaded
launchctl list | grep ai.praison

Config reload did not apply

Symptom: You edited gateway.yaml or sent SIGHUP, but channels or agents still run the old configuration.
CheckWhat to look for
Log lineA successful reload logs a summary such as reload applied: agents; restart[telegram] — if absent, the watcher may not have fired or SIGHUP was ignored (Windows has no SIGHUP)
Drain windowChannel restarts wait up to gateway.reload_drain_timeout (falls back to drain_timeout) — a slow turn can delay the visible restart
Installpip install "praisonai[gateway]" enables watchdog; without it, mtime polling (about 5 s) still reloads but more slowly
See Gateway Config Reload for file-watch vs SIGHUP paths and YAML keys.

Multi-Channel Troubleshooting

Common failure modes when using multiple bots on the same platform:
SymptomCauseFix
Token ${X} is used by multiple channelsTwo channels reference the same env var in bot.yamlGive each channel its own env var and create a separate bot in @BotFather
Same bot token value is used by multiple channelsTwo different env vars resolve to the same actual tokenGenerate a fresh token from @BotFather for the duplicate channel
Channel '<x>' token '<env>' doesn't follow naming conventionCustom env var nameRename to PLATFORM_<ROLE>_BOT_TOKEN (e.g. TELEGRAM_CFO_BOT_TOKEN)
Missing token: <env>Env var referenced in bot.yaml is unsetAdd it to ~/.praisonai/.env
Example Fix:
# Problem: Both channels use the same token
# Error: "Token TELEGRAM_BOT_TOKEN is used by multiple channels"

# Solution: Create unique tokens per role
# 1. Create new bot in @BotFather for CFO role
# 2. Add unique environment variable
export TELEGRAM_CFO_BOT_TOKEN="987654321:DEF..."

# 3. Update bot.yaml
channels:
  telegram_cfo:
    platform: telegram
    token: ${TELEGRAM_CFO_BOT_TOKEN}  # Unique token
    routes:
      default: cfo
Validation:
# Check multi-channel configuration
praisonai doctor multi_channel_tokens

# ✅ Expected output:
# "Multi-channel configuration looks good (N channels)"

Channel Supervision Issues

Channel goes silent but /health shows running: true

Symptom: Channel stops receiving messages but /health still reports "running": true. Cause: Pre-PR-2041 behaviour, or the health: block is missing from gateway.yaml — hung sockets are not detected until an exception is raised. Fix: Add the proactive health block:
gateway:
  health:
    interval: 300
    stale_after: 120
    enabled: true
See Proactive Health Monitoring.

Channel keeps restarting every 5 minutes

Symptom: Channel restarts on a regular interval visible in logs. Cause: stale_after too low for a quiet channel, or interval too aggressive for a slow remote API. Fix: Raise stale_after to e.g. 600, or lower max_restarts_per_hour so the cap kicks in and surfaces the issue:
gateway:
  health:
    stale_after: 600
    max_restarts_per_hour: 3

Channel Shows state: failed in /health

Symptom: When checking GET /health, a channel shows "state": "failed" with error details. Common Causes:
  • Telegram Conflict: Multiple bot instances using the same token
  • Invalid Credentials: Bot token revoked or incorrect
  • Permission Issues: Bot lacks required permissions
Investigation Steps:
1

Check Error Details

curl http://127.0.0.1:8765/health | jq '.channels.telegram.supervision'
Look for last_error and last_error_time fields.
2

Telegram Conflict Resolution

If error contains “Conflict: terminated by other getUpdates”:
# Stop any other bot instances using the same token
# Then force reconnect to reset state
praisonai gateway reconnect telegram
3

Credential Verification

For invalid token errors, verify your bot token:
# Test token directly
curl "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getMe"

Channel Keeps Retrying Forever

Symptom: High total_recoveries count, constant retry attempts visible in logs. Investigation:
# Check supervision status
curl http://127.0.0.1:8765/health | jq '.channels'

# Look for:
# - High total_recoveries value
# - next_retry_at timestamp
# - last_error details
Resolution:
# Temporarily pause while investigating
praisonai gateway pause telegram

# Investigate root cause (network, DNS, etc.)
# Fix underlying issue

# Resume when ready
praisonai gateway resume telegram

Config Migration

When praisonai doctor --only gateway_config_migration reports Config can be migrated, your YAML uses a legacy shape that loads correctly but can be rewritten to the canonical format.
1

Detect migration opportunities

praisonai doctor --only gateway_config_migration
Example WARN output:
⚠ Gateway Config Migration [MEDIUM]
  Config can be migrated: 2 change(s)
  • telegram: allowed_users string → list migration available
  • Set telegram.group_policy to secure default 'mention_only'
2

Understand auto-normalisation

At load time, GatewayConfigSchema already normalises legacy formats — your bot runs without rewriting the file. Persist the canonical form when you want the on-disk YAML to match what the schema produces.
3

Apply canonical YAML

Legacy shapeCanonical form
Top-level platform + tokenchannels: dict with one entry
BotOS platforms: dictchannels: dict (same keys)
allowed_users: "id1,id2" (string)allowed_users: ["id1", "id2"] (list)
See Gateway Config Migration for before/after YAML.

Environment Variables in Config

Gateway and bot configs support ${VAR} substitution in any string value. Resolution order:
  1. Process environment variables
  2. ~/.praisonai/.env (loaded automatically; override path with PRAISONAI_ENV_FILE)
# Verify all referenced variables resolve
praisonai doctor --only gateway_env_substitution
Unset variables cause validation to FAIL at load time and in the gateway_env_substitution doctor check.

Best Practices

Always run praisonai gateway status before diving into logs - it shows port, PID, and daemon state in one command.
Always use praisonai gateway stop before restarting - this drains active sessions and prevents data loss.
When in doubt, run praisonai onboard - it handles daemon setup, credentials, and port configuration automatically.
If bot-stderr.log grows rapidly, you have a crash loop - stop the daemon, upgrade PraisonAI, then restart.

Gateway CLI

Gateway command reference

Gateway Server

Gateway configuration and setup