Skip to content

Playbooks

Every entry here is a current, published revision, shown with the reproduction counts behind its confidence band — never a bare percentage.

  1. Diagnosing a Bun panic loading a native addon

    Confirms the failure is specific to Bun (by checking the same code under plain Node) before treating it as a Bun compatibility regression, then checks for a documented compatible module/Bun version pairing to pin to. This is intentionally left diagnostic rather than prescriptive beyond that point: Bun's native-addon compatibility is an evolving, partial implementation, and asserting a specific cause for a specific version pair without checking that pair's actual changelog/issues would be a guess, not a fact.

    Bun
    Unverifiedno reproductions yetWhy this confidence?
  2. Diagnosing containerd task-creation timeouts

    Narrows a context-deadline-exceeded failure to node-level resource pressure versus containerd being slowed by a large pile-up of stale containers/images on one node. It does not cover a genuinely crashed containerd daemon (a different, more obvious failure mode) or CNI-level sandbox failures that don't mention containerd task creation specifically.

    Kubernetescontainerdkubectl
    Unverifiedno reproductions yetWhy this confidence?
  3. Fixing CoreDNS SERVFAIL from a detected forwarding loop

    Confirms the crash is genuinely the loop plugin (not an unrelated SERVFAIL cause), traces it to the node's resolv.conf in the common case, and fixes it by forwarding to explicit upstream resolvers instead. It does not cover SERVFAIL caused by an actually-unreachable upstream DNS server, NetworkPolicy blocking egress from CoreDNS, or CoreDNS being resource-starved — those don't log the loop-plugin message and need a different diagnosis.

    CoreDNSKuberneteskubectl
    Unverifiedno reproductions yetWhy this confidence?
  4. Fixing D1 "no such table" after a migration that seemed to run

    Covers the two most common causes: applying a migration to the wrong local/remote target, and a Worker binding pointing at a different database_id than the one that was migrated. Does not cover a migration file that itself has a SQL error (that fails loudly at apply time, not later as "no such table"), or drift specifically caused by an ORM's own migration tracking — see the Drizzle-specific playbook for that.

    Cloudflare D1Wrangler
    Unverifiedno reproductions yetWhy this confidence?
  5. Fixing D1 SQLITE_BUSY errors from concurrent writes

    Covers SQLITE_BUSY caused by two or more write requests colliding on the same D1 database (including a Worker request racing a Cron Trigger), and by a single invocation issuing many unbatched writes in a row. Does not cover SQLITE_BUSY from an actually-stuck transaction left open by a crashed process, or D1's separate CPU-time/memory-limit resets — those return different, more specific error messages.

    Cloudflare D1Cloudflare Workers
    Unverifiedno reproductions yetWhy this confidence?
  6. Handling D1 UNIQUE constraint violations

    Covers genuine duplicate-key inserts and the check-then-insert race that produces the same error under concurrency. Does not cover foreign-key constraint failures (a different SQLITE_CONSTRAINT variant) or CHECK-constraint failures — those need a different diagnosis of the data itself, not of insert timing.

    Cloudflare D1
    Unverifiedno reproductions yetWhy this confidence?
  7. Fixing D1's "too many API requests by single worker invocation" error

    Covers the D1-specific per-invocation request cap being hit by an N+1 query pattern or by combining many D1 calls with other subrequests in one invocation. Does not cover the general Workers subrequest limit for fetch()-only Workers with no D1 involved (see Workers platform limits), and does not cover D1's separate CPU-time or memory-limit resets, which return different error text entirely.

    Cloudflare D1Cloudflare Workers
    Unverifiedno reproductions yetWhy this confidence?
  8. Handling Durable Object WebSocket disconnects on deploy

    Covers the expected, documented behaviour that a code update terminates a Durable Object's WebSockets, and gradual deployments extending the window this can happen in. Does not cover WebSocket drops unrelated to deploys (idle timeouts, client network loss, or missing ping/pong handling) — rule those out first if the disconnects don't line up with a deploy.

    Cloudflare Durable ObjectsCloudflare Workers
    Unverifiedno reproductions yetWhy this confidence?
  9. Fixing Durable Object storage operation timeouts

    Covers oversized single writes and misuse of blockConcurrencyWhile() as the two most common causes of a Durable Object storage timeout. Does not cover the equivalent, differently-worded timeout message that D1 itself surfaces (D1 runs on Durable Objects internally, but its error text and remediation — sharding queries, not blockConcurrencyWhile — are D1-specific, not this playbook).

    Cloudflare Durable Objects
    Unverifiedno reproductions yetWhy this confidence?
  10. Fixing 'Cannot connect to the Docker daemon'

    Checks whether the daemon is actually running, then whether DOCKER_HOST or the active Docker context is pointing somewhere unexpected. It also flags the socket-permission lookalike ('Got permission denied' rather than 'Cannot connect') as a distinct message with a distinct fix, so it isn't mistaken for a dead daemon.

    Docker
    Unverifiedno reproductions yetWhy this confidence?
  11. Fixing 'exec format error' in a container

    Checks the image's recorded architecture against the host's before assuming a CPU mismatch, fixes it with a multi-arch build, and verifies. If architectures already match, it falls back to the second real cause of this exact message: a script whose shebang line is missing or corrupted (commonly by CRLF line endings). It does not cover exec format error thrown by a genuinely corrupted or truncated binary unrelated to architecture or shebangs.

    DockerDocker Buildx / BuildKit
    Unverifiedno reproductions yetWhy this confidence?
  12. Fixing DrizzleError from a missing column or table on D1

    Covers schema.ts drifting ahead of the generated migrations, and a migration that exists but was applied to only one of D1's local/remote targets. Does not cover Drizzle Studio or Drizzle Kit connection errors (a different failure mode with different messages), and does not cover the equivalent D1_ERROR: no such table thrown outside of Drizzle — see the general D1 migration-not-applied playbook for that.

    Cloudflare D1Drizzle ORM
    Unverifiedno reproductions yetWhy this confidence?
  13. Clearing a Helm release stuck pending-upgrade / pending-install

    Confirms the release really is stuck in a pending-* state with nothing genuinely in flight, then clears it — via helm rollback when a prior successful revision exists, or by removing the stuck release record when there isn't one (a first install that never completed). It does not cover a helm upgrade that is genuinely still running, or Helm 2's separate Tiller-based failure modes.

    Helmkubectl
    Unverifiedno reproductions yetWhy this confidence?
  14. Triaging CrashLoopBackOff to its actual cause

    Uses kubectl describe pod's Last State reason, exit code and Events to sort a CrashLoopBackOff into one of five common causes and points at the right next step for each. It deliberately does not fix any of them in depth — the OOM branch, for instance, defers to the dedicated OOMKilled playbook — and it does not cover ImagePullBackOff, FailedScheduling or CreateContainerConfigError, which are different pod conditions with their own playbooks.

    Kuberneteskubectl
    Unverifiedno reproductions yetWhy this confidence?
  15. Diagnosing FailedScheduling / Insufficient cpu

    Separates a transient shortfall from nodes still rejoining after an upgrade, genuine cluster-wide CPU contention needing more capacity, and a pod whose CPU request is simply too large to fit on any node in the pool at all. It does not cover FailedScheduling caused by node affinity, taints/tolerations, or Insufficient memory/pods — the same describe-pod approach applies, but the resource name in the message and the fix differ.

    Kuberneteskubectl
    Unverifiedno reproductions yetWhy this confidence?
  16. Fixing ImagePullBackOff caused by private-registry credentials

    Walks from the exact pull error through the pod's imagePullSecrets to the actual Secret content, fixing a missing secret reference, an expired token, or a wrong registry host/namespace. It explicitly does not cover a missing or mistyped image tag ('manifest unknown', 'repository does not exist') — that's a different error and a different fix — and it is not a general Docker registry-login guide: a successful `docker pull` on a developer's laptop proves the credentials are valid outside the cluster, it does not prove the pod itself has them wired up.

    Kuberneteskubectl
    Unverifiedno reproductions yetWhy this confidence?
  17. Diagnosing and fixing an OOMKilled container

    Confirms a genuine OOM kill from kubectl describe pod, then distinguishes a memory limit that's simply undersized from a leak-shaped growth pattern that raising the limit would only delay. Covers raising the memory request/limit as a concrete fix; it does not do in-app memory profiling or cover node-level memory pressure evictions, which are a different mechanism from a per-container limit kill.

    Kuberneteskubectl
    Unverifiedno reproductions yetWhy this confidence?
  18. Fixing kubectl 'the server doesn't have a resource type'

    Rules out the wrong-cluster case first, then checks whether the resource is a CRD that was never applied, isn't yet Established, or is being hidden from discovery by RBAC or a broken aggregated API. It does not cover ordinary typos in a resource name that IS registered — kubectl's own suggestion output usually catches those — and it is not a guide to writing CRDs.

    Kuberneteskubectl
    Unverifiedno reproductions yetWhy this confidence?
  19. Diagnosing Neon serverless driver WebSocket connection failures

    Covers the two things this error almost always traces back to — a connection string or driver entry point that isn't the one meant for this runtime, and isolating whether the failure is Worker-specific. Does not cover general Postgres server-side connection issues once the WebSocket itself connects successfully — those are covered by the general Postgres playbooks.

    Cloudflare WorkersNeon
    Unverifiedno reproductions yetWhy this confidence?
  20. Diagnosing ingress-nginx 504 Gateway Time-out

    Splits 504s into a slow-backend branch (raise the per-Ingress timeout for a legitimately slow endpoint, or fix backend contention if it's overload-shaped) and a no-live-upstream branch (no Ready endpoints, or a Service/NetworkPolicy blocking traffic to an otherwise-healthy pod). It does not cover 502/503 responses, which usually mean the backend actively refused or reset the connection rather than never answering, or client-side timeouts that never reach the ingress at all.

    KubernetesNGINX Ingress Controllerkubectl
    Unverifiedno reproductions yetWhy this confidence?
  21. Diagnosing a missing module npm install silently didn't provide

    Confirms the module truly isn't installed, then checks the two most common install-time reasons: a platform-specific optionalDependency (native addons like esbuild/sharp binaries) skipped because the install environment's OS/architecture didn't match the runtime environment's, and a lockfile out of sync with package.json. It does not cover an ESM 'ERR_MODULE_NOT_FOUND' extension or exports-map error, which is a resolution-time problem with a package that IS installed, covered by a separate playbook.

    Node.js
    Unverifiedno reproductions yetWhy this confidence?
  22. Freeing a port stuck with EADDRINUSE

    Identifies what actually holds the port, checks whether it's an orphaned instance of the same app versus a different legitimate service, and verifies the port is free afterward. It does not cover a port genuinely reserved by the OS or blocked by a firewall — EADDRINUSE specifically means something is bound, not that access is denied.

    Node.js
    Unverifiedno reproductions yetWhy this confidence?
  23. Diagnosing Node.js ECONNREFUSED

    Confirms nothing is actually listening at the target address, then splits between a host/port misconfiguration (wrong address for where the dependency actually lives) and a startup-order race (the app connects before its dependency is ready). It does not cover connection timeouts (ETIMEDOUT), which point at network reachability rather than an actively refused connection, and it isn't specific to any one dependency — the same triage applies whether the target is a database, cache, or another service.

    Node.js
    Unverifiedno reproductions yetWhy this confidence?
  24. Diagnosing ERR_MODULE_NOT_FOUND after upgrading Node

    Node's ESM resolver rules around mandatory file extensions and 'exports' enforcement are not new in Node 22 — the summary is important here: the upgrade is usually the trigger only because it came with a lockfile/dependency refresh, not because Node itself changed how it resolves modules. Splits the failing specifier into your own relative import (missing extension) versus a dependency (its exports map tightened). It does not cover a plain 'Cannot find module' with no ERR_ prefix right after npm install — that's a CommonJS-style resolution failure covered by a separate playbook.

    Node.js
    Unverifiedno reproductions yetWhy this confidence?
  25. Diagnosing a V8 heap-limit crash that isn't a container OOM-kill

    Covers telling a V8 heap-limit crash apart from a container/orchestrator OOM-kill (a different failure with no application log line at all), and the two independent responses: raising V8's ceiling versus finding a leak. Does not cover Kubernetes OOMKilled pod eviction — that's a distinct failure mode, at a different layer, with its own playbook, even though both are commonly described as 'ran out of memory'.

    Node.jsV8
    Unverifiedno reproductions yetWhy this confidence?
  26. Diagnosing node-postgres connection timeouts at startup

    Covers distinguishing pool exhaustion from a genuine reachability/auth failure, which node-postgres reports identically, and the immediate config-side responses to each. Does not cover a pool that starts healthy and exhausts gradually under sustained traffic from a code-level leak — that's the missing-release playbook, a different root cause with the same visible error.

    node-postgres (pg)
    Unverifiedno reproductions yetWhy this confidence?
  27. Finding and fixing a node-postgres connection leak

    Covers the specific signature of a client-side leak — pool usage climbing steadily under sustained normal traffic rather than in a burst — and the try/finally fix. Does not cover a pool that's simply undersized for a legitimate concurrent burst at startup; that's the connect-timeout playbook, a different pattern in the same counters.

    node-postgres (pg)
    Unverifiedno reproductions yetWhy this confidence?
  28. Diagnosing PgBouncer's max_client_conn limit

    Covers PgBouncer's own client-facing connection ceiling — a different limit from Postgres's max_connections and from PgBouncer's server-side pool sizing. Does not cover prepared-statement errors under transaction pooling (see the two prepared-statement playbooks) or Postgres running out of connections directly (see the postgres-too-many-clients playbook).

    PgBouncer
    Unverifiedno reproductions yetWhy this confidence?
  29. Fixing 'prepared statement does not exist' under PgBouncer transaction pooling

    Covers the PgBouncer-side mechanism and its two fixes: native prepared-statement tracking (1.21+) or avoiding named server-side prepared statements. Does not cover postgres.js's mirror-image 'already exists' error, which shares the same underlying incompatibility but needs a client-side fix, not a PgBouncer-side one — see the postgres.js playbook, which is not interchangeable with this one despite the similar wording.

    PgBouncerPostgreSQL
    Unverifiedno reproductions yetWhy this confidence?
  30. Diagnosing and preventing Postgres deadlocks (40P01)

    Covers reading the log detail Postgres already wrote, identifying the lock-ordering mismatch, and enforcing a consistent order. Does not cover SQLSTATE 40001 serialization failures — a different SQLSTATE and a different mechanism entirely, with its own playbook — and does not cover finding a leak; a deadlock always resolves itself within about a second whether or not anyone looks at it.

    PostgreSQL
    Unverifiedno reproductions yetWhy this confidence?
  31. Diagnosing and handling Postgres serialization failures (40001)

    Covers confirming this is a genuine repeatable-read/serializable conflict and adding the application-level retry that Postgres's own documentation prescribes. It does not cover deadlocks (SQLSTATE 40P01 — a different mechanism entirely, see the deadlock playbook) and does not attempt to tune away contention at the schema level.

    PostgreSQL
    Unverifiedno reproductions yetWhy this confidence?
  32. Diagnosing Postgres connection exhaustion (too many clients already)

    Covers the shortest path to confirming you're actually out of connections, finding who's holding them, and the immediate relief versus durable fix. Does not cover PgBouncer's own client-limit error (see the PgBouncer playbook) or ORM/driver-specific pool leaks beyond pointing at the node-postgres playbooks that cover them in depth.

    PostgreSQL
    Unverifiedno reproductions yetWhy this confidence?
  33. Fixing postgres.js 'prepared statement already exists' under PgBouncer

    Covers postgres.js's own automatic-prepare feature specifically and its documented fix, `prepare: false`. Does not cover the PgBouncer-side 'does not exist' error or PgBouncer's own max_prepared_statements setting — that's a related but distinct incompatibility with a different remedy, covered in the PgBouncer prepared-statement playbook; the two are not interchangeable even though both involve prepared statements and PgBouncer.

    PgBouncerpostgres.js
    Unverifiedno reproductions yetWhy this confidence?
  34. Fixing PrismaClientInitializationError from a missing or bad connection string

    Covers environment/connection-string configuration specifically: the string never reaching the deploy environment, a name mismatch against what schema.prisma expects, or unescaped special characters. Does not cover P1001 (a valid-looking connection string that simply can't reach the server over the network) — that's a separate playbook — and does not cover query engine binary/platform mismatches beyond flagging them as a possibility.

    Prisma
    Unverifiedno reproductions yetWhy this confidence?
  35. Diagnosing Prisma P1001 (can't reach database server)

    Covers confirming basic network reachability to the named host:port and the usual reasons it's blocked. Does not cover a missing or malformed connection string (see the PrismaClientInitializationError playbook) — by the time you have a specific host:port in the error, the string was parsed successfully.

    Prisma
    Unverifiedno reproductions yetWhy this confidence?
  36. Handling Prisma P2002 unique constraint violations

    Covers recognising that P2002 is Postgres's unique constraint doing its job, correctly, and the two idiomatic ways to handle an expected duplicate. Does not cover tracing where an unexpected duplicate came from (a retry without an idempotency key, a double-fired webhook, a bad backfill) — this playbook only gets you to recognising which situation you're in.

    PostgreSQLPrisma
    Unverifiedno reproductions yetWhy this confidence?
  37. Fixing R2 SignatureDoesNotMatch on presigned URLs

    Covers the URL being altered after signing (re-encoding, reordering, or stripping of query parameters) and signing with a stale or wrong secret key. Does not cover expired presigned URLs, which R2 reports as a separate error code, ExpiredRequest — check that first, since the fix is completely different (just regenerate the URL).

    Cloudflare R2
    Unverifiedno reproductions yetWhy this confidence?
  38. Diagnosing a Supabase RLS INSERT rejection

    Covers confirming which policies exist and why WITH CHECK is rejecting the row, and adding a correct INSERT policy. Does not cover RLS for SELECT/UPDATE/DELETE (governed by USING, a different clause) or auth/JWT configuration beyond noting that the SQL editor bypasses RLS entirely and so can never be used to test a policy.

    PostgreSQLSupabase
    Unverifiedno reproductions yetWhy this confidence?
  39. Fixing Workers CPU time limit exceeded (Error 1102)

    Covers genuine CPU-time exhaustion (heavy synchronous computation) and distinguishes it from a request that's merely slow because it's waiting on a subrequest — waiting time never counts toward CPU time, so that case needs a different fix entirely. Does not cover memory-limit resets (a different error, "Exceeded Memory") or the free-plan daily request cap (Error 1027).

    Cloudflare WorkersWrangler
    Unverifiedno reproductions yetWhy this confidence?
  40. Debugging Workers Error 1101 (uncaught exception)

    Covers finding and fixing the underlying JavaScript exception behind Error 1101, including the "script will never generate a response" variant caused by an unresolved promise. Does not cover Error 1102 (CPU time limit exceeded — a resource limit, not a thrown exception) or Error 1015 (rate limiting) — those have separate, more specific causes and remedies.

    Cloudflare WorkersWrangler
    Unverifiedno reproductions yetWhy this confidence?
  41. Fixing "Cannot perform I/O on behalf of a different request"

    Covers the module-level-caching anti-pattern for I/O objects (Request/Response/streams/database clients) in Workers. Does not cover the Cache API, which is the correct, supported way to cache actual HTTP responses across requests — this playbook is specifically about accidentally reusing the live object rather than its data.

    Cloudflare Workers
    Unverifiedno reproductions yetWhy this confidence?
  42. Fixing wrangler d1 execute --remote hanging with no output

    Covers the interactive-confirmation-prompt cause (the most common one, especially in CI or piped/backgrounded shells) and network connectivity to the Cloudflare API as a secondary cause. Does not cover a command that's genuinely still running against a very large file — check for real progress (network/CPU activity) before assuming it's stuck.

    Cloudflare D1Wrangler
    Unverifiedno reproductions yetWhy this confidence?