Contributing

Debugging playbook

Symptoms that have happened before, what caused them, and where to look first.

Many of Ghost's hardest bugs passed every test and appeared only at real size, real latency or real concurrency. This table is the institutional memory.

SymptomLikely causeWhere
Push fails with no ref update commandsThe request stream was left unattended across an await and the command section was droppedADR 0013, git-raw-body.middleware.ts
Pushes above ~1 MiB fail with HTTP 400 … the remote end hung up before dataThe flush-only probe answered as a malformed pushADR 0014, isProbeRequest
RangeError: data is too long on a huge pushSomething holds a pack in a Buffer past 2 GiBADR 0015
Clones of one repository return 500 after a strange pushA ref in the log names an object nobody has; pre-0034 logsADR 0034, repair-repositories.ts
A clone comes back empty with no errorHEAD names a branch that does not existensureHead in the materializer
A ref you wrote into a cache disappearsThe next materialize reconciles refs to the snapshotADR 0012
A fork's pull request reports "conflicts" that are not realThe head's objects were not lent; merge-tree exit 1 with stderr is an error, not a conflictADR 0016
Dates off by a few hoursA timestamp without time zoneADR 0018
500s under concurrent pushes that look like S3 flakinessA 409 ConditionalRequestConflict treated as an error instead of a retryADR 0005
WalContentionError (503)Eight lost compare-and-swaps in a row on one repositoryADR 0007
SSH fetch reports remote transport reported error though it workedA pipe ended the channel before exit-statusADR 0019
Large SSH fetches truncatedThe connection closed before the channel drainedsame
gh fails with a GraphQL validation error naming a fieldThe field or type is missing; check gh-capture.spec and the conformance testGitHub compatibility
gh can't paginateMissing Link headerlinkHeader
e2e tests time out or collideRun with --no-file-parallelism; check the root .env is not leaking config into the test appTesting
An integration test changed your dataIt ran against your dev database. Never set TEST_DATABASE_URL to itTesting
Docker image build fails at bun install --frozen-lockfileA workspace was added without copying its package.json in that DockerfileSelf-hosting

General moves

  • Reproduce at size. Push a real, large repository (a 2 GiB one has found two bugs). Use a remote bucket, not just RustFS on localhost, when latency could matter.
  • Read the log. Download repos/<id>/index and decode it (the Storage chapter's script). Compare refs with the cache's git for-each-ref. The log is the truth; if the cache disagrees, the cache is wrong.
  • Wipe the cache. Deleting $TMPDIR/ghost/<id>.git is always safe and rules the cache out.
  • Trace it. With lgtm running, Grafana's Tempo shows each request's spans down to pg queries and S3 calls.
  • Search the ponytail: comments near the code; known shortcuts are written there with their ceilings.

On this page