Troubleshooting
Common issues and how to resolve them.
Setup and Configuration
protege doctor returns unhealthy
Run the detailed check:
protege doctor --jsonCommon causes:
- Missing config file — run
protege setuporprotege initto regenerate - No personas created — create one with
protege persona create "My Agent" - Missing API key — check that the required env var is set in
.secrets(e.g.,ANTHROPIC_API_KEY=sk-ant-...) - Invalid
extensions/extensions.json— verify JSON syntax and that all referenced extensions exist
Web search fails with "missing environment variable"
The web-search tool needs an API key for its configured provider:
# Add to .secrets
TAVILY_API_KEY=tvly-...
# or
PERPLEXITY_API_KEY=pplx-...Then restart any running gateway process so the new env is loaded.
Gateway
protege status shows gateway not running
# Start it
protege gateway start
# If a stale PID file is the issue, stop first
protege gateway stop
protege gateway startGateway starts but no emails arrive
Check if relay is connected:
bashprotege logs --scope gateway --tail 50Look for
gateway.relay.authenticatedevents.If using local SMTP, verify
configs/gateway.jsonhas correcthostandportsettings and that the port is reachable.Verify the sender isn't blocked by the access policy:
bash# Check configs/security.json # Make sure the sender address matches an allow rule
Outbound emails aren't delivered
Check logs for delivery events:
bashprotege logs --scope gateway --tail 100Look for
gateway.outbound.sentorgateway.outbound.sent_via_relay.Verify outbound transport is configured — either
transportblock inconfigs/gateway.jsonorrelay.enabled: true.If using relay, check that the relay server is running and the connection is active.
If using direct SMTP, verify your transport credentials and that the SMTP server is reachable.
Email Threading
Gmail replies create new threads instead of continuing
- The default behavior uses same-thread reply mode — this should work correctly.
- Check if the LLM is explicitly requesting
threadingMode: "new_thread". - Verify outbound emails include
In-Reply-ToandReferencesheaders:bashprotege logs --scope gateway --tail 100
Emails land in spam
If using relay mode with your own relay server:
- Configure SPF for the relay domain
- Set PTR/rDNS for the relay IP
- Publish a DMARC policy
- Check your relay IP isn't on any blocklists
Chat
"Persona not found" error
# List available personas
protege persona list
# Use the full ID or an unambiguous prefix
protege chat --persona 5d5291bc3285362f
protege chat --persona 5d52Sending does nothing in an existing thread
Existing threads (from real email) are read-only in chat v1. To chat with your agent:
- Press
Ctrl+Nto create a new writable thread - Press
ito enter compose mode - Type and press
Ctrl+Sto send
Ctrl+Enter doesn't send
Terminal emulators handle Ctrl+Enter inconsistently. Use Ctrl+S as the primary send shortcut.
Scheduler
Scheduler won't start
# Check if node-cron is installed
npm ls node-cron
# If missing
npm install node-cron@4.2.1Scheduled tasks run but no emails arrive
- The gateway must be running for outbound email:bash
protege gateway start - Verify outbound transport is configured (either
transportorrelay.enabled: trueinconfigs/gateway.json). - Check scheduler logs:bash
protege logs --scope scheduler --tail 100
Tasks appear backlogged
Check the concurrency limit in configs/system.json:
{
"scheduler": {
"max_global_concurrent_runs": 5
}
}If runs are consistently queuing, increase the limit carefully. Also check if individual runs are taking too long (e.g., slow LLM responses or tool calls).
Failure Alerts
Alert emails aren't sent
- Set
admin_contact_emailinconfigs/system.json:json{ "admin_contact_email": "admin@example.com" } - Verify with
protege doctor --json - Check for
gateway.alert.*andscheduler.alert.*events in logs
Daemon (Linux)
Daemon restarts in a loop (exit code 127)
The ExecStart path in the systemd unit is stale (e.g., Node.js or Protege was reinstalled to a different location):
protege daemon reinstall --user
protege daemon start --userMultiple workspaces cause ambiguity
Use --unit to pin the exact unit:
protege daemon status --user --unit protege-gateway-abc123.service
protege daemon logs --user --unit protege-gateway-abc123.service --followOr check which units exist:
protege daemon info --user --json
