registry/internal/database/migrations
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Tadas Antanavicius 3dc4f93370
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)
2025-09-30 10:21:48 +03:00
..
001_initial_schema.sql Refactor database implementation to use PostgreSQL instead of MongoDB (#289) 2025-08-22 01:40:28 +01:00
002_add_server_extensions.sql Allow for vendor extensions on servers (#298) 2025-08-23 09:59:03 +01:00
003_simplify_to_key_value.sql Implement flattened _meta format for server extensions (#331) 2025-09-01 19:27:23 +01:00
004_update_meta_field_format.sql Fix _meta field format for MCP spec compliance (#367) 2025-09-08 11:40:04 -07:00
005_add_server_id_rename_version_id.sql Introduce serverId, rename id to versionId (#465) 2025-09-21 15:00:09 +03:00
006_migrate_server_json_camelcase.sql add migraiton file to convert snake case to camel case (#522) 2025-09-21 15:26:15 +03:00
007_add_publish_constraints.sql Fix race conditions in concurrent server publishing (#528) 2025-09-22 12:16:05 +01:00
008_separate_official_metadata.sql fix: handle NULL status values in migration 008 (#578) 2025-09-30 10:21:48 +03:00