Commit 3dc4f93
authored
fix: handle NULL status values in migration 008 (#578)
## Problem
Production deployment is failing with CrashLoopBackOff. Migration 008
fails with:
```
ERROR: column "status" of relation "servers" contains null values (SQLSTATE 23502)
```
## Root Cause
The migration extracts the `status` field from an unexpected location in
the data structure.
### Actual Data Structure (Before Migration)
In the current format, `status` is at the **top level** of the JSON, not
nested in official metadata:
```json
{
"name": "com.example/server",
"version": "1.0.0",
"status": "active", ← STATUS IS HERE (top level)
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "uuid",
"publishedAt": "2025-09-01T00:00:00Z",
"isLatest": true
// NO STATUS FIELD HERE
}
}
}
```
For 120 out of 765 servers, the status field is **missing entirely**:
```json
{
"name": "com.biodnd/agent-ip",
"version": "0.1.2",
// ← NO STATUS FIELD AT ALL
"_meta": {
"io.modelcontextprotocol.registry/official": {
"serverId": "uuid",
"publishedAt": "2025-09-23T09:47:07Z",
"isLatest": true
// STILL NO STATUS FIELD HERE
}
}
}
```
### Original Migration Logic
```sql
IF official_meta IS NOT NULL THEN
UPDATE servers
SET
status = (official_meta->>'status'), -- Extracts NULL for all servers
```
**Result:**
- All 765 servers would have NULL status extracted
- Because `official_meta->>'status'` returns NULL (field doesn't exist
there)
- The migration tries to add `NOT NULL` constraint → fails
### Fixed Migration Logic
```sql
IF official_meta IS NOT NULL THEN
UPDATE servers
SET
status = COALESCE(NULLIF(rec.value->>'status', 'null'), 'active'),
```
**Result:**
- Extracts from top-level JSON where status actually exists
- `NULLIF(rec.value->>'status', 'null')` handles edge case of literal
string "null"
- `COALESCE(..., 'active')` provides fallback when status is missing
- All servers get valid status value
### Impact Breakdown
**645 servers with `"status": "active"`:**
- Before fix: Would extract NULL → migration fails
- After fix: Extracts "active" correctly
**120 servers with missing status field:**
- Before fix: Would extract NULL → migration fails
- After fix: Defaults to 'active' via COALESCE
## Example Servers with Missing Status
(First 9 discovered during investigation)
- com.biodnd/agent-ip
- io.github.jkakar/cookwith-mcp
- com.joelverhagen.mcp/Knapcode.SampleMcpServer
- io.github.Lyellr88/marm-mcp-server
- com.biodnd/agent-press
- io.github.timheuer/sampledotnetmcpserver
- io.github.CodeCraftersLLC/local-voice-mcp
- com.biodnd/agent-fin
- io.github.ruvnet/ruv-swarm
## Testing
Verified against production data (765 total servers):
- ✅ All servers have official metadata
- ✅ None have status in official metadata (expected)
- ✅ 645 have "status": "active" at top level
- ✅ 120 have missing status field (no field present)
- ✅ Fix extracts from correct location for all cases
## Impact
This unblocks production deployment. Once merged and released as v1.2.1,
the migration will:
1. Extract status from the correct location (top-level JSON)
2. Handle missing status fields with sensible defaults
3. Successfully add NOT NULL constraint
4. Allow pods to start normally
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)1 parent bef665a commit 3dc4f93
File tree
1 file changed
+3
-2
lines changed- internal/database/migrations
1 file changed
+3
-2
lines changedLines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
38 | 39 | | |
39 | 40 | | |
40 | | - | |
| 41 | + | |
41 | 42 | | |
42 | 43 | | |
43 | 44 | | |
| |||
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
49 | | - | |
| 50 | + | |
50 | 51 | | |
51 | 52 | | |
52 | 53 | | |
| |||
0 commit comments