Skip to main content
Common issues with the PraisonAI Gateway daemon and server, with step-by-step troubleshooting guides.
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.
1

Check PID lock and port status

Look for lines like:
  • Gateway PID lock: Process 12345 running (127.0.0.1:8765)
  • Port 127.0.0.1:8765: In use
Since PraisonAI ≥ PR #4197, the lock file records a PID + start-time fingerprint. A stale lock is only reclaimed when the recorded PID has genuinely exited (or its start time no longer matches). A live process the current user cannot signal (foreign uid) is treated as running — start refuses, status reports it as running, and the lock is preserved. Before this fix, a cross-uid gateway could be silently displaced and a second gateway could start on the same bot token.
2

Stop the existing gateway gracefully

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

This sends SIGKILL directly (SIGTERM on Windows) for immediate termination.
4

If port is used by non-gateway process

5

Clean up stale lock file (if needed)

Stale locks are automatically detected and removed, but you can clean them manually if needed.

SSL Certificate Verify Failed on Start (Corporate Proxy / MITM)

Symptom: praisonai gateway start --config gateway.yaml fails with an SSLCertVerificationError in gateway doctor, but the same channel token works fine with --no-preflight. Cause: Your network intercepts TLS with a corporate CA the probe’s HTTP client does not trust yet. The runtime bot adapter is often more permissive, so the token itself is usually fine. Fix (pick one):
1

Point PraisonAI at your corporate CA (preferred)

PRAISONAI_SSL_CA_BUNDLE overrides any pre-existing SSL_CERT_FILE and REQUESTS_CA_BUNDLE for the probe.
2

Use the standard SSL env vars

3

Skip the preflight check

Skips channel-credential validation on start. Use only when you know the tokens are good.
Preflight soft-fails on SSL-only errors — it prints a warning naming these three env vars and continues to start automatically. You only need the fixes above if you also want a clean gateway doctor run. A mixed SSL + token/network failure still hard-aborts. See Corporate CA bundle (SSL-inspecting networks).
A configured-but-missing CA bundle path prints Warning: CA bundle path '<path>' does not exist — SSL_CERT_FILE / REQUESTS_CA_BUNDLE not updated for probe. and does not touch the SSL env vars. Double-check the path resolves before restarting.

Gateway start aborts with ‘Turn pre-flight failed’

Symptom: praisonai gateway start exits with:
Cause: The channel credentials are valid, but the resolved agent’s model provider credential is missing / invalid / rate-limited / out of quota. The startup real-turn check (--verify-turn, on by default) sends one "ping" prompt to the agent and the model round-trip failed. Fix (any of):
1

Add the model/provider API key

2

Reproduce interactively

3

Temporarily skip the turn check

Or set gateway.preflight.verify_turn: false in bot.yaml. Use only when you know the model key is good (e.g. constrained/offline environments).
The turn pre-flight is independent of --preflight — it catches most REASON_MISSING_KEY / REASON_AUTH_PERMANENT credential problems at startup instead of on the first inbound message. See Gateway Readiness → Turn pre-flight.

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.
Since PR #4197, the cross-uid variant of this symptom is fixed on main: a gateway owned by another user is now treated as running, so its lock is preserved and a second gateway is refused rather than started on the same token. Before the fix, a foreign-uid gateway was reported dead, its lock was deleted, and a duplicate poller could start.
1

Stop all gateway instances

This ensures all instances are terminated, even if PID files are corrupted.
2

Verify no processes are running

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

Start a single gateway instance

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

Look for Running status and process ID.
2

Check daemon logs for errors

Look for Python tracebacks or port binding errors.
3

Check port and PID lock 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

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

Restart the daemon


Rapidly Growing Log Files

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

Check log file size

If growing rapidly (>1MB/min), this indicates a crash loop.
2

View recent errors

Look for repeated Python tracebacks, especially IndentationError.
3

Stop the daemon

4

Clear logs and restart


Daemon Not Installed

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

Run the onboarding wizard

This installs the daemon service for your platform.
2

Verify installation

Should show Installed but not running or Running.
3

Start the service


HTTP 500 on Health Endpoint

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

Check PraisonAI version

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

Upgrade PraisonAI

3

Restart the gateway

4

Test health endpoint

Should return JSON with status, uptime, agents, sessions, clients, and channels.

Windows: gateway status shows PID lock status: Unavailable

Symptom: praisonai gateway status prints an advisory PID-lock line, followed by a healthy gateway:
On older versions (pre-v4.6.141) the same underlying cause produced a harder failure that hid the status entirely:
Root cause: On Windows, os.kill(pid, 0) — used by GatewayPIDLock._is_process_running to poll whether a lock is stale — can raise SystemError (“returned a result with an exception set”) instead of OSError / ProcessLookupError. Before PraisonAI v4.6.141 that exception propagated through GatewayHandler.status and short-circuited the /health probe, so operators saw no gateway status at all. What v4.6.141 changes:
  1. _is_process_running now catches SystemError and ValueError and returns False (process not running).
  2. GatewayHandler.status treats PID-lock inspection as advisory only. Any unexpected exception prints PID lock status: Unavailable (<error>) and the command continues to the /health probe.
1

Check your version

Upgrade to ≥ v4.6.141 if you still see ERROR: Error checking gateway server status: returned a result with an exception set.
2

Read the line as advisory

If praisonai gateway status now prints PID lock status: Unavailable (<error>) followed by Gateway Status: healthy, the gateway is running — the PID line is advisory only.
3

Confirm with the health endpoint

A 200 healthy response confirms the gateway is up regardless of the PID-lock line.
4

Inspect the lock file if needed

The lines are pid, host, port, timestamp, and (since PR #4197) a create_time start-time fingerprint. The 5th line may be empty on older 4-line locks or when psutil is unavailable — the lock then degrades to the previous PID-only check. A stale PID is cleaned up automatically on the next start/stop/status call.
Related: PraisonAI #2844, fixed by PR #2849.

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

If this command runs without error, you have the fix from PR #1754.
2

Upgrade to a fixed version

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

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.

Clean Reinstall Process

When all else fails, perform a clean reinstall:
1

Stop and uninstall

2

Clear configuration

3

Upgrade PraisonAI

4

Run onboarding

Follow the wizard to reinstall the daemon service.
5

Verify installation

Should show daemon running and gateway reachable.

Client stops reconnecting after agent_not_found

Symptom: GatewayClient logs Connection abandoned: agent_not_found (reconnect paused; not retrying) and stops attempting to connect, even though the gateway is healthy. Cause: The agent_id supplied in the client’s hello frame is not registered on the gateway. The server emits agent_not_found with next_step: do_not_retry, and the client now correctly stops the reconnect loop instead of backing off forever.
1

Check the agent_id you pass

2

List agents registered on the gateway

Compare against the id you’re passing.
3

Fix the id or register the agent

Either update the client’s agent_id, or add the agent to the gateway configuration and restart it. Then call client.connect() again — the fresh call clears any stale backoff floor from the previous cycle.
4

Surface the failure without log scraping

Setting client.on_reconnect_paused before connect() gives you an immediate callback with (code, next_step) so the failure surfaces without waiting for a log scrape. See Gateway Client → Terminal vs Transient Connect Errors.

Cross-instance messages not being delivered / Redis pub/sub outage

Symptom: Subscribers on gateway B stop seeing messages that were published on gateway A. praisonai gateway status shows push.redis_degraded: true and a growing push.redis_dropped_writes; health()["degraded_owners"] lists route:redis-pubsub. Cause: The Redis pub/sub connection that fans out channel messages across gateway instances dropped. Cross-instance delivery pauses until the adapter reconnects.
1

Confirm the degraded owner and its retry_hint

Look for push.redis_degraded: true and a route:redis-pubsub entry whose retry_hint points you at praisonai gateway doctor.
2

Run gateway doctor

Surfaces the same record with the actionable hint.
3

Verify Redis reachability from the gateway host

A PONG confirms Redis is reachable; if it fails, fix the Redis connection or network path.
Recovery: No manual intervention on the gateway is needed. Once Redis is reachable again the adapter reconnects with bounded exponential backoff (1s → 30s cap), re-subscribes every channel, and clears route:redis-pubsub from degraded_owners. The log line to look for is Redis push adapter reconnected (server_id=<uuid>).
Any publish / presence / message-store writes made while degraded were counted (push.redis_dropped_writes) and not buffered — they are gone from the cross-instance transport’s perspective.
See Real-Time Push Notifications → HA & cross-instance delivery for the full contract.

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. Example envelope received on rate-limit:
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

This automatically generates and saves a secure token.
2

Or set token manually

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

2

Or allow defaults for demos (unsafe)

Gateway refuses to start: gateway.auth_token is weak/placeholder

Symptom: doctor or start refuses with “gateway.auth_token is a known-weak/placeholder value”. Preview the repair, then apply it — --fix mints a strong token and re-validates:
1

Preview (writes nothing, exits 1)

2

Apply (mints, persists, re-validates)

An explicit weak auth_token in gateway.yaml is rewritten in place. ${ENV} references are left alone — they resolve from ~/.praisonai/.env, which --fix already updated. See Gateway CLI › Auto-repair.

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

2

Or check environment variables

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

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):

Diagnostic Commands

Quick commands for gathering diagnostic information:

Platform-Specific Notes

LaunchAgent Path: ~/Library/LaunchAgents/ai.praison.bot.plist Log Path: ~/.praisonai/logs/bot-stderr.log

Config reload did not apply

Symptom: You edited gateway.yaml or sent SIGHUP, but channels or agents still run the old configuration. 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: Example Fix:
Validation:

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:
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:

Every channel restarts at once — fleet crash-loop breaker tripped

Symptom: One of:
  • Log line Fleet crash-loop breaker TRIPPED: holding channel restarts (...).
  • praisonai gateway status shows fleet.breaker_tripped: true.
  • list_degraded() / GET /health shows a gateway owner with owner_id: "fleet".
Cause: A systemic upstream fault — a bad shared provider, a network partition, or an org-wide expired token — is restarting every channel at once. The fleet-level breaker tripped one aggregate breaker instead of letting each channel silently burn its own max_restarts_per_hour budget.
1

Diagnose the shared cause

Look for the shared provider / token / network issue behind the storm — a single fault is affecting all channels.
2

Fix the underlying fault

Rotate the shared token, restore the provider, or heal the network partition. While the breaker is tripped, restarts are held on purpose — you do not need to restart the gateway.
3

Wait one cooldown, then confirm recovery

After the cause is fixed, wait one breaker_cooldown_s (default 120s). The breaker re-arms cleanly and the gateway/fleet degraded entry clears on the next monitor sweep — no manual poll needed. Confirm with:

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

Look for last_error and last_error_time fields.
2

Telegram Conflict Resolution

If error contains “Conflict: terminated by other getUpdates”:
3

Credential Verification

For invalid token errors, verify your bot token:

Channel Keeps Retrying Forever

Symptom: High total_recoveries count, constant retry attempts visible in logs. Investigation:
Resolution:

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

Example WARN output:
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

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)
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