Skip to content

[bug] cap never recovers after redis restart #299

Description

@sschmidt

bug description:
When the redis/valkey backend restarts (crash, OOM, pod reschedule, planned maintenance), the standalone server never reconnects.

Cap creates a single Bun RedisClient in standalone/src/db.js and relies on its autoReconnect. That reconnect logic doesn't appear to be stable in Bun:

Since cap has no reconnect/recreate handling of its own, the broken client is kept forever.

affects:

  • standalone
  • widget (ui)
  • widget (wasm solver)
  • js server
  • js solver

to reproduce:

  1. Run standalone (tiago2/cap:latest) against redis or valkey, e.g. via the bundled docker-compose.yml or in kubernetes.
  2. Create a site key and verify POST /<siteKey>/challenge returns 200.
  3. Restart the redis server (docker restart cap-valkey / delete the redis pod). It is back and accepting connections within ~2 seconds.
  4. Keep requesting POST /<siteKey>/challenge.

Result: after one ERR_REDIS_CONNECTION_TIMEOUT, every subsequent request fails with ERR_REDIS_CONNECTION_CLOSED — observed for 5+ minutes (151 consecutive failures) with no recovery, while a freshly created RedisClient from inside the same container connects and gets PONG immediately. Restarting cap fixes it instantly.

expected behavior:

After redis is reachable again, cap should reconnect and continue serving requests without a process restart.

screenshots:

API response after the redis restart (stays like this forever):

{"success":false,"error":"ERR_REDIS_CONNECTION_CLOSED","detail": "troubleshooting":"http://trycap.dev/guide/standalone/..."}}

Log output — one connection timeout at the moment redis goes away, then an endless stream of ERR_REDIS_CONNECTION_CLOSED for every request:

[ERR_REDIS_CONNECTION_TIMEOUT 0e1999447f4a] {"timestamp":"2026-08-13T13:20:07.092Z","error":{"name":"RedisError","message":"Connection timeout reached after 10000ms","code":"ERR_REDIS_CONNECTION_TIMEOUT"},"env":{"bun":"1.3.14","platform":"linux",...}}
[ERR_REDIS_CONNECTION_CLOSED c383e2cc0033] {"timestamp":"2026-08-13T13:20:09.116Z","error":{"name":"RedisError","message":"Connection has failed","stack":"RedisError: Connection has failed\n    at hget (unknown)\n    at <anonymous> (/usr/src/app/src/cap.js:209:38)\n    at <anonymous> (/usr/src/app/src/ratelimit.js:70:30)\n    at handle (file:///usr/src/app/node_modules/elysia/dist/compose.mjs:10:27)\n    at map (file:///usr/src/app/node_modules/elysia/dist/adapter/bun/compose.mjs:9:67)\n    at processTicksAndRejections (native:7:39)","code":"ERR_REDIS_CONNECTION_CLOSED"},"env":{"bun":"1.3.14","platform":"linux",...}}
[ERR_REDIS_CONNECTION_CLOSED 5765415ffbb8] {"timestamp":"2026-08-13T13:20:11.147Z","error":{"name":"RedisError","message":"Connection has failed", ...}}
[cap] RSW keypair refresh failed: Connection has failed
[ERR_REDIS_CONNECTION_CLOSED 82cdaf1aa496] ... (repeats for every request until cap is restarted)

versions and environment:
cap standalone 3.1.9 (tiago2/cap:latest), Bun 1.3.14, redis:7-alpine

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions