Troubleshooting

Diagnose common startup and configuration failures on a self-hosted stack.

Most problems show up at startup. Start with the service state and the API logs:

Terminal
cd ~/sdp
docker compose ps
docker compose logs -f sdp-api

Docker is not ready

The install script checks Docker first. If it reports that Docker isn't installed, that Compose v2 is unavailable, or that the daemon isn't reachable, install or start Docker and retry. See the Docker Engine and Compose install guides.

A required variable is missing

compose.yml stops with a message such as set POSTGRES_PASSWORD in .env when a required variable is unset. Make sure .env sits next to compose.yml and sets every required variable. The configurator writes a complete file, and the environment reference lists what's required.

Images won't pull

If docker compose pull reports access denied or a missing manifest:

  • Check that SDP_IMAGE_REGISTRY and SDP_VERSION name a registry and tag you can reach. Release tags look like vX.Y.Z.
  • Pull one image directly to see the underlying error, for example docker pull ghcr.io/solana-foundation/sdp/sdp-api:latest.
  • If the registry is private, run docker login for it first.

Port already in use

The API, dashboard, and docs use ports 8787, 3000, and 3001 by default. If another process holds one, that service can't bind. Set SDP_API_PORT, SDP_WEB_PORT, or SDP_DOCS_PORT in .env, update the browser-facing URLs that name that port (the NEXT_PUBLIC_* URLs, and FRONTEND_URL for the dashboard), and run docker compose up -d again.

Migrations failed

sdp-migrate runs before the API starts. If it fails, the API stays down. Read its logs:

Terminal
docker compose logs sdp-migrate

A failure here is usually a database connection problem. Check POSTGRES_* (or DATABASE_URL), and that postgres shows as healthy in docker compose ps.

Database connection refused

The API and migrations wait for Postgres to report healthy before they start. If they still can't connect, check the credentials in .env. With an external database (DATABASE_URL set), check that it's reachable from inside the Docker network.

Dashboard sign-in fails

Most sign-in failures are Clerk configuration. Check NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY, and CLERK_ISSUER against your Clerk application, and that the keys belong to the instance (development or production) you mean to use. Then look for these messages:

  • Clerk token missing organization or Clerk token has no usable email claim, in the failing request's 401 response: the session token lacks the claims in the Clerk setup guide.
  • Clerk session refused: not issued to the dashboard, in the API logs: FRONTEND_URL isn't the origin the dashboard loads from. With ENVIRONMENT=production, the API accepts only sessions issued to that origin.

The local signer isn't offered

If the local provider is missing from the dashboard, CUSTODY_PRIVATE_KEY isn't set. If choosing it returns Local requires manual activation for this organization., add the organization override from First devnet deployment, and check that the Clerk webhook reaches the API.

Still stuck?

Collect the failing service's logs and your .env settings with the secrets removed, then open an issue on the project repository.