Troubleshooting
Start with the error message, check the local file or process it names, and then retry the smallest command that failed.
init says the instance directory is not empty
init refuses to use a folder that already contains files.
Use a new folder or move the existing files before trying again:
mv ./stage-data ./stage-data-old
stage-pg init ./stage-data --tls-cert /path/server.crt --tls-key /path/server.key
Do not delete the old folder unless you are sure it contains no database you need.
init says TLS certificate or key is missing
The certificate and private key must exist before PostgreSQL is initialized:
ls -l /etc/stage-pg/postgres.crt /etc/stage-pg/postgres.key
The private key must not be readable by group or other users:
chmod 600 /etc/stage-pg/postgres.key
stage-pg does not create certificates. Get them from the CA or certificate system you already use.
init or run cannot find PostgreSQL tools
Make sure all of these are installed and on the same major version:
initdb --version
pg_ctl --version
psql --version
pg_dump --version
pg_restore --version
If they are not on PATH, pass their directory during init:
stage-pg init ./stage-data \
--tls-cert /path/server.crt \
--tls-key /path/server.key \
--postgres-bin-dir /usr/lib/postgresql/17/bin
PostgreSQL major version mismatch
The version in config.json must match the PostgreSQL tools that stage-pg finds. Check the configured value and the installed tools:
jq '.postgresMajor' ./stage-data/config.json
pg_dump --version
Use the matching binary directory or recreate the instance with the intended major version.
port ... is already in use
Each instance gets one stable port. Another process or another instance already owns the selected port.
Check the listener with your operating system tools, then stop the conflicting process or choose a different instance host. Do not edit the port while the instance is running or while Cloudflare/Tailscale still point at the old value.
cloudflared fails to start
Check the local token file and executable:
ls -l /etc/stage-pg/cloudflared-token
cloudflared --version
The token file must be a readable regular file with restrictive permissions. stage-pg does not test Cloudflare reachability before starting, so a local run failure and a remote Worker connection failure are different problems.
Tailscale administrators cannot connect
Check each part of the path:
PostgreSQL is running with
stage-pg run.Tailscale Serve uses the saved port on both sides:
tailscale serve statusThe tailnet policy allows the administrator to reach that port.
The client uses the Tailscale hostname, the saved port, the
stage_adminrole, and PostgreSQL TLS.
stage-pg does not create the Serve rule or tailnet policy for you.
Backup fails
Check the PostgreSQL tools and the local backup directory:
pg_dump --version
ls -ld ./stage-data/backups
An incomplete .part file can be removed after the failed command. A published .dump file should be kept unless its manifest or checksum is invalid.
S3 upload fails but a local dump exists
This is expected behavior for an upload-only failure. Check the AWS-style environment variables and bucket settings:
test -n "$AWS_ACCESS_KEY_ID" && echo access key is set
test -n "$AWS_SECRET_ACCESS_KEY" && echo secret key is set
The local dump remains the usable backup. Fix the credentials or endpoint and run stage-pg backup again.
Restore reports a checksum or manifest error
Do not restore an artifact that fails verification. Copy a fresh dump from the original backup location or S3, then retry:
stage-pg restore ./stage-data ./stage-data/backups/20260807T180000Z.dump
Restore always targets a new database. It does not overwrite the live staging database when validation fails.