/api/health reports acledIntel: {status: EMPTY, records: 0, maxStaleMin: 38} (crit) — the only live data outage among the current DEGRADED problems. Railway shows seed-conflict-intel green.
Every key this seeder owns is gone from prod Redis
conflict:acled:v1:all:0:0 EXISTS=0 TTL=-2
conflict:acled-resolution:v1:all:0:0 EXISTS=0 TTL=-2
intel:pizzint:v1:base EXISTS=0 TTL=-2
intel:pizzint:v1:gdelt EXISTS=0 TTL=-2
seed-meta:conflict:acled-intel MISSING
Not just the primary — the auxiliary feeds it writes before the primary are gone too. The seeder is yielding nothing at all.
Three failures stacked
1. No ACLED credentials. fetchAcledToken() (scripts/seed-conflict-intel.mjs:74-97) reads ACLED_EMAIL+ACLED_PASSWORD (OAuth) or ACLED_ACCESS_TOKEN (legacy static). The Railway service has neither — the only ACLED-ish var is VITE_ACLED_ACCESS_TOKEN, which is both a name the seeder never reads and set to an empty string. So the primary feed is never even attempted. (This is the same root cause as #5136, which tracks the downstream forecast-resolution damage.)
2. The GDELT fallback (#5099) is dead upstream. With no creds the seeder falls back to the GDELT article-volume proxy. From the live run log:
[GDELT] proxy (curl) attempt 1/1 failed (non-retryable): ... curl: (56) CONNECT tunnel failed, response 522
GDELT conflict-events fallback failed: coverage below floor: 0/20 countries succeeded (min 16)
ACLED: no credentials + GDELT fallback empty — publishing auxiliary feeds only, primary feed left empty
Not a Railway-egress problem: api.gdeltproject.org also times out (HTTP 000 after 25s) from a residential IP. GDELT itself is unreachable right now.
3. The exit-0 zero-yield loop hides both. With every source dead the run returns 0 records, so runSeed takes the RETRY path — which only extends TTLs on keys that still exist. Ours had already expired:
WARNING: 2 key(s) were expired/missing — EXPIRE was a no-op; manual seed required
RETRY: declareRecords returned 0 (zeroIsValid=false) — envelope unchanged, TTL extended, bundle will retry next cycle
=== Done (85684ms, RETRY) === <- exit 0 -> Railway paints it GREEN
So the fleet-health tooling reports this seeder as perfectly healthy while its data is permanently gone. manual seed required is printed to a log nobody reads and nothing acts on it.
Fixes
- Restore the primary (unblocks everything): set
ACLED_EMAIL + ACLED_PASSWORD on seed-conflict-intel. This also removes the dependence on GDELT, which the feed should never have been resting on.
- Harden the class bug (separate, and the more important one): a run that yields zero records and finds its keys already expired should not exit 0. Today
EXPIRE was a no-op; manual seed required is a fatal data condition dressed up as a green badge. Either exit non-zero on that state, or write a status: error seed-meta so /api/health reports SEED_ERROR instead of waiting for a TTL to lapse into EMPTY. Any seeder on the RETRY path can hit this.
Found while triaging the DEGRADED /api/health that also produced #5254 (forecastBets) and #5255 (defensePatents). Related: #5136, #5099.
https://claude.ai/code/session_014xoeVpgK3YJtUcr4t5VzF4
/api/healthreportsacledIntel: {status: EMPTY, records: 0, maxStaleMin: 38}(crit) — the only live data outage among the currentDEGRADEDproblems. Railway showsseed-conflict-intelgreen.Every key this seeder owns is gone from prod Redis
Not just the primary — the auxiliary feeds it writes before the primary are gone too. The seeder is yielding nothing at all.
Three failures stacked
1. No ACLED credentials.
fetchAcledToken()(scripts/seed-conflict-intel.mjs:74-97) readsACLED_EMAIL+ACLED_PASSWORD(OAuth) orACLED_ACCESS_TOKEN(legacy static). The Railway service has neither — the only ACLED-ish var isVITE_ACLED_ACCESS_TOKEN, which is both a name the seeder never reads and set to an empty string. So the primary feed is never even attempted. (This is the same root cause as #5136, which tracks the downstream forecast-resolution damage.)2. The GDELT fallback (#5099) is dead upstream. With no creds the seeder falls back to the GDELT article-volume proxy. From the live run log:
Not a Railway-egress problem:
api.gdeltproject.orgalso times out (HTTP 000 after 25s) from a residential IP. GDELT itself is unreachable right now.3. The exit-0 zero-yield loop hides both. With every source dead the run returns 0 records, so
runSeedtakes the RETRY path — which only extends TTLs on keys that still exist. Ours had already expired:So the fleet-health tooling reports this seeder as perfectly healthy while its data is permanently gone.
manual seed requiredis printed to a log nobody reads and nothing acts on it.Fixes
ACLED_EMAIL+ACLED_PASSWORDonseed-conflict-intel. This also removes the dependence on GDELT, which the feed should never have been resting on.EXPIRE was a no-op; manual seed requiredis a fatal data condition dressed up as a green badge. Either exit non-zero on that state, or write astatus: errorseed-meta so/api/healthreportsSEED_ERRORinstead of waiting for a TTL to lapse intoEMPTY. Any seeder on the RETRY path can hit this.Found while triaging the
DEGRADED/api/healththat also produced #5254 (forecastBets) and #5255 (defensePatents). Related: #5136, #5099.https://claude.ai/code/session_014xoeVpgK3YJtUcr4t5VzF4