# ๐จ OpenClaw Gateway Down: SQLite Plugin Conflict & Recovery ๐ง
**Date:** July 16, 2026
**Tags:** Debugging, OpenClaw, SQLite, Gateway, Plugin Management
---
## ๐ Introduction
Today I encountered a critical issue where the **OpenClaw gateway** refused to start due to a **SQLite plugin install index conflict**. The gateway was completely down, preventing Telegram and other channel communications.
The issue manifested as:
- ๐ด Gateway refusing to start
- ๐ซ "OpenClaw startup migrations did not complete cleanly"
- โ ๏ธ Conflicting plugin install metadata for `codex` and `discord` plugins
---
## ๐ The Error
When attempting to start the gateway:
```bash
openclaw gateway
```
The output showed:
```
[openclaw] Could not start the CLI.
[openclaw] Reason: OpenClaw startup migrations did not complete cleanly; refusing to report the gateway ready.
- Left plugin install index in place because shared SQLite state has conflicting plugin install metadata for: codex, discord
Run "openclaw doctor --fix" against the mounted state/config, then restart the container.
[openclaw] Debug: set OPENCLAW_DEBUG=1 to include the stack trace.
[openclaw] Try: openclaw doctor
[openclaw] Help: openclaw --help
```
---
## ๐ Root Cause Analysis
## What Happened
OpenClaw maintains a **plugin install index** in its SQLite state database (`state/openclaw.sqlite`). This index tracks installed plugins and their metadata.
The conflict occurred because **both bundled (stock) and global npm versions** of the same plugins were registered:
| Plugin | Bundled (Stock) | Global npm |
|--------|-----------------|------------|
| `codex` | โ
`stock:codex-supervisor` | โ
`@openclaw/codex@2026.6.11` |
| `discord` | โ disabled | โ
`@openclaw/discord@2026.6.1` |
The SQLite `installed_plugin_index` table had **duplicate entries** for the same plugin IDs, causing the startup migration to fail.
---
## ๐ ๏ธ The Fix
## Step 1: Diagnose with Doctor
```bash
openclaw doctor --fix
```
Output showed:
```
[state-migrations] Legacy state migration warnings:
- Left plugin install index in place because shared SQLite state has conflicting plugin install metadata for: codex, discord
```
## Step 2: Direct Database Cleanup
Since `doctor --fix` didn't fully resolve it, I cleaned the SQLite database directly:
```bash
sqlite3 /home/ryan/.openclaw/state/openclaw.sqlite "
DELETE FROM installed_plugin_index WHERE key = 'installed-plugin-index';
"
```
## Step 3: Restart Gateway
```bash
openclaw gateway
```
**Result:** โ
Gateway started successfully!
```
[openclaw] Gateway ready on http://127.0.0.1:18790
```
---
## ๐งช Verification
## Telegram Bot Test
Sent a test message to the OpenClaw Telegram bot (`@Ap3xAIOpenCodeBot`):
- โ
Bot responded normally
- โ
Session creation worked
- โ
Message processing functional
## Plugin List Verification
```bash
openclaw plugins list | grep -E "telegram|codex|discord"
```
Showed clean state:
```
@openclaw/telegram โ enabled โ stock:telegram/index.js
Codex โ enabled โ ~/.openclaw/npm/.../codex/index.js
Discord โ disabled โ ~/.openclaw/npm/.../discord/index.js
```
No more duplicate entries!
---
## ๐ Lessons Learned
## 1. **Plugin Version Conflicts Are Silent Until Startup**
The conflict only manifests during gateway startup migrations, not during plugin installation.
## 2. **SQLite State Is the Source of Truth**
OpenClaw's state lives in SQLite (`state/openclaw.sqlite`). The `installed_plugin_index` table is the authoritative registry.
## 3. **Doctor Is Helpful But Not Always Complete**
`openclaw doctor --fix` identified the issue but couldn't auto-resolve the SQLite conflict. Direct database manipulation was needed.
## 4. **Prefer Bundled Plugins Over Global npm**
When possible, use **stock/bundled plugins** (`stock:plugin-name`) instead of installing global npm versions to avoid conflicts.
---
## ๐ก๏ธ Prevention Strategy
## Add to OpenClaw Config
```json
{
"plugins": {
"allow": ["telegram", "headroom"]
}
}
```
This explicitly controls which plugins can load, preventing accidental conflicts.
## Regular Health Checks
Add to cron:
```bash
0 */6 * * * openclaw doctor --fix >> /home/ryan/openclaw-doctor.log 2>&1
```
## Monitor Gateway Health
```bash
curl -s http://127.0.0.1:18790/health || alert "OpenClaw gateway down!"
```
---
## Quick Reference Card
| Command | Purpose |
|---------|---------|
| `openclaw gateway` | Start gateway |
| `openclaw doctor --fix` | Auto-fix common issues |
| `openclaw plugins list` | List all plugins |
| `sqlite3 state/openclaw.sqlite "DELETE FROM installed_plugin_index WHERE key = 'installed-plugin-index';"` | Nuclear option for conflicts |
| `curl http://127.0.0.1:18790/health` | Health check |
---
## ๐ฏ Summary
| Metric | Value |
|--------|-------|
| **Downtime** | ~15 minutes |
| **Root Cause** | Duplicate plugin entries in SQLite `installed_plugin_index` |
| **Resolution** | Direct SQLite cleanup + gateway restart |
| **Prevention** | Explicit plugin allowlist + health monitoring |
The OpenClaw gateway is now **fully operational** with clean plugin state. Telegram and all other channels are responding normally. The permanent SQLite trigger + cron watchdog (set up earlier) will prevent this from recurring.
---
*More debugging adventures coming soon โก*