Troubleshooting
Fixes for the problems people hit most: missing login codes, being logged out, Stripe purchases without a license, activation limits and webhooks.
Most problems people run into with Keygate come down to a handful of settings. Start with the server log: Keygate says what it refused and why.
Signing in
Why don't I receive the login code?
If no email provider is set up, Keygate writes the code to the server log instead; with Docker run docker compose logs keygate | grep "OTP code". If email is set up, use Send Test Email in the email settings to check it. Each address can request three codes every ten minutes. And if sign ups are limited to emails that hold a license, an unknown address gets no code at all, on purpose.
Why does the code work but I stay logged out?
When BASE_URL starts with https, Keygate marks its login cookie as secure, and browsers drop secure cookies on plain http pages. This happens when you open Keygate by IP address or over http while BASE_URL says https, for example before the reverse proxy is set up. Open Keygate at the address in BASE_URL. If your proxy talks to Keygate over plain http, that is fine as long as visitors reach the proxy over HTTPS.
Why won't Keygate start?
Keygate checks its settings at startup and stops if one is missing or wrong, and the log names it. The usual causes are a JWT_SECRET shorter than 32 characters, a LICENSE_SIGNING_KEY that is not exactly 64 hex characters, an ENVIRONMENT other than development, staging or production, and storage settings filled in only partly.
Payments
A customer paid in Stripe but no license appeared. What went wrong?
Look in the server log. stripe webhook auto-setup failed means Stripe cannot reach BASE_URL, which has to be a public HTTPS address. could not resolve plan means the price that was bought is not set on any plan; add the price ID to the plan so future purchases work, and use Issue License for the customer who already paid. Also check that the install and the purchase use the same mode, test or live.
License checks
Why does activation fail with ACTIVATION_LIMIT?
Every device slot on the license is taken. The customer can free one in the customer portal, or your app can call deactivate on the old device. If this happens to customers who only use one computer, your app is probably sending an identifier that changes between runs, so every start looks like a new device.
Why does verify return LICENSE_NOT_FOUND for a key that exists?
Verify answers the same way for every failure so that keys cannot be guessed. The most common reason is that this device was never activated, so call activate first. Otherwise the license may be suspended, revoked or expired, which the license page in the dashboard shows.
Why does my app get 429 LOCKED_OUT?
Five failed license calls from one IP address within five minutes lock that address out, for 30 seconds the first time and twice as long each time after that, up to 30 minutes. It usually means someone is guessing keys, or your app is retrying a wrong key in a loop. The limits can be changed with BF_MAX_FAILS and BF_LOCKOUT_SECONDS.
Webhooks and updates
Why aren't webhooks delivered to my local receiver?
Keygate refuses to deliver to private, loopback and link local addresses so that a webhook cannot be used to reach your internal network. For a receiver on the same machine or Docker network, set WEBHOOK_ALLOW_PRIVATE=true.
Why does the update feed answer 401 LICENSE_KEY_REQUIRED?
The product requires a license on its feeds. The updater has to send the license key in an X-License-Key header, or the signed token from verify in an X-License-Token header or as license_token in the URL.
Why do releases answer STORAGE_DISABLED?
Release hosting needs S3 compatible storage. Set STORAGE_BUCKET, STORAGE_ACCESS_KEY, STORAGE_SECRET_KEY and RELEASE_KEY_ENCRYPTION_KEY, plus STORAGE_ENDPOINT for anything other than AWS S3, and restart Keygate.
Still stuck? Ask in GitHub Discussions with the relevant lines from the server log.
Last updated October 4, 2026