Skip to main content
Each entry below names the symptom the way you would describe it, then gives the cause and the fix.

Startup and access

Compose exits with a message about POSTGRES_PASSWORD or AUTH_SECRET. Both are required in the root .env and Compose refuses to start when either is missing or empty. Generate them, then start again.
Two settings stop the API at boot.
  • AUTH_SECRET is shorter than 32 characters. The API refuses to run with a weak signing secret. Generate one with openssl rand -hex 32 and recreate the API container.
  • AUTH_COOKIE_SECURE is false while NODE_ENV is production, which the Docker image always sets. The log reads AUTH_COOKIE_SECURE must be true when NODE_ENV is production. Set it back to true and see Sessions do not persist behind a proxy for ways to reach the stack without TLS. See What the API refuses to start with.
A failed migration also stops the API at boot. The log then reports P3018 or P3009 and names the migration. See If a migration fails.
Registration closed automatically once the owner account existed, which is the default. Set AUTH_ALLOW_REGISTRATION=true and restart the API. See Authentication and accounts.
AUTH_SECRET changed, which invalidates every session signature. Personal API tokens are unaffected. See Rotate secrets.
AUTH_COOKIE_SECURE=true marks the cookie Secure, so a browser reaching the site over plain HTTP from another machine discards it. Setting it to false is not an option, because the Docker image then refuses to boot. Pick one of these instead.
  • Terminate TLS in front of port 3001 with your own reverse proxy and certificate.
  • Compose the Cloudflare Tunnel overlay, which terminates TLS at Cloudflare.
  • Forward the port over SSH and open http://localhost:3001 in Chrome or Firefox, which keep a Secure cookie on localhost without TLS. Safari does not. See Signing in returns to the sign in form.
See Hosting behind TLS and a reverse proxy.
The API accepted the registration or the password, but the browser did not keep the session cookie, so the next request arrived signed out. The form then shows the message “Your browser did not keep the session cookie”. On an older release, registering lands on the sign in form and signing in simply loads it again. The cookie is Secure, and a browser stores it only over HTTPS or on an origin it treats as secure. Three causes cover almost every case.
  • Safari on plain HTTP, even on localhost. Chrome and Firefox keep a Secure cookie on http://localhost and http://127.0.0.1. Safari drops it there, so http://localhost:3001 accepts the sign in and bounces straight back. WebKit tracks the gap as bug 281149, and the MDN compatibility data records it for Set-Cookie. Safari 27.0 announces support for Secure cookies on loopback hosts, but the change depends on the system cookie storage, and on macOS 26.6 that storage still drops the cookie, so Safari 27.0 there behaves as before.
  • Plain HTTP from another machine. A LAN address or any hostname that is not loopback is not a secure origin in any browser.
  • Cookies blocked for the site. A browser setting, extension or policy that blocks all cookies discards the cookie even over HTTPS.
To confirm, open the developer tools and register or sign in. A POST /api/backend/auth/register that answers 201, or a POST /api/backend/auth/login that answers 200, with a Set-Cookie: asobeast_session header, followed by no stored asobeast_session cookie, is this problem.Pick one fix.
  • Use Chrome or Firefox for a local evaluation on http://localhost:3001.
  • Put TLS in front of the stack. For a local evaluation that works in Safari, run Caddy with the Caddyfile below and open https://localhost. Caddy signs the certificate with its own local authority, which the system has to trust before Safari accepts it.
  • Compose the Cloudflare Tunnel overlay for a host you reach from elsewhere.
Set TRUST_PROXY=1 as Bring your own proxy describes. Do not set AUTH_COOKIE_SECURE=false to get past this, because the Docker image then refuses to boot.

Admin surfaces

You are not signed in as the owner in that browser. The surface answers 404 rather than 403 so it does not confirm it exists. Sign in and reload, or check that BULL_BOARD_ENABLED is not false. See The queue dashboard and the OpenAPI surface.
An earlier release let the operator suspend the bootstrap workspace, which takes the support surface and the queue dashboard away from the operator’s own credentials. Restore the workspace from the command line, see Suspending and restoring from the command line. Current releases refuse that suspension.
API_DOCS defaults to owner, which gates the documentation routes the same way. Sign in as the platform operator, or set API_DOCS=public if the surface should be readable by anyone. See The queue dashboard and the OpenAPI surface.
With billing on, the admin area, /admin/queues, /docs and /metrics open only while the operator’s own workspace has a plan in force, so a lapsed trial or a trial still waiting for the email confirmation closes all of them. Confirm the email if the notice asks for it, choose a plan on the upgrade page, or set plan on the bootstrap workspace in the database. See When the operator’s workspace has no plan.
The workspace ws_default was erased while other accounts survived, which older releases allowed from Settings. Check for it.
No row means the operator is gone. Register a fresh account, which gets a workspace of its own, then give that account the bootstrap workspace. Registration is closed by default once accounts exist, so set AUTH_ALLOW_REGISTRATION=true and restart the API for the sign up, then set it back to false and restart again. An existing account whose workspace holds no apps works as well and needs no sign up. Replace the email with the account you chose.
The account is the platform operator from its next request, with no restart and no new sign in. The workspace it registered with stays behind empty and can be left alone. Use a fresh account rather than a customer’s, because a user takes no data with it: the apps and keywords of the workspace it leaves stay there. On an instance with BILLING_ENABLED=true the admin surfaces also need an entitled operator, so add "plan" to the insert with 'ultimate' as its value. See Deleting the operator workspace.

Collection

The daily pipeline starts at CRON_DAILY, which defaults to 0 3 * * * and is evaluated in UTC rather than in your local timezone. Check pipeline.lastDailyRunAt on /api/backend/health, then look at the queue dashboard for stuck or failed jobs. See The daily pipeline and rate limits.
The parser canary confirmed that a store stopped parsing, so collection is paused for that store. The banner appears after two consecutive failing canary runs rather than on the first, so a single blip is never announced, and it clears on its own within a minute of the canary returning ok. Your stored history is untouched: a break pauses collection, it does not remove anything. Nothing on your side needs changing. See Recover from a broken store parser.
Not a failure. The keyword was checked and the app was not found within the captured depth, which defaults to 200. The bound is read from that row’s own depth. See Positions and rank depth.
Both workers run at concurrency 1 behind a rate limiter, so a large keyword and market count simply takes longer. As the platform operator, check the request budget card on the settings page or GET /jobs/budget. Remove keywords or markets rather than raising the limits, which risks the store throttling your IP address. See The daily pipeline and rate limits.
Failed jobs from before the upgrade are still counted. The badge reads the failed job count of the store and alert queues, and a failed job stays in that count until it is removed, so failures from a keyword the upgrade paused keep the badge degraded. Sign in as the platform operator, open /admin/queues, select the store queue, open its failed jobs and clean them. The badge recovers on the next health check. See The queue dashboard and the OpenAPI surface.
Expected after an upgrade that changes the scoring formula. Each score row records the formulaVersion that produced it, and the API queues one rescore for every tracked keyword whose latest score used an older version, through the same rate limited queues as weekly scoring. Until its job runs, a keyword keeps its old numbers and the table says “Older formula”. A large list takes a while: about 100 minutes per 150 App Store keywords at the default rate limit. See Popularity, difficulty and opportunity.
A store changed a response shape. The failure is contained to the provider layer, the job fails, and BullMQ retries it with backoff while request handling continues. See Recover from a broken store parser for triage, containment and recovery.

Alerts and AI

The endpoint returned a non 2xx status, which the delivery log records per channel on the settings page. Fix the endpoint, then use flush now to claim the facts currently pending. See Send alerts.
Email stays disabled until both SMTP_HOST and SMTP_FROM are set. One without the other leaves it off. Check the delivery log for a relay rejection, which usually means the envelope sender is not on a domain the relay accepts. Mail that arrives but lands in spam needs the sending domain authenticated. See Email deliverability.
Account email is recorded like alert email. Every attempt writes a row to the delivery log on the account channel, with the event naming what it was for, verification, recovery or invitation, and one of three outcomes.Read the rows with the database the deployment already has.
The same outcomes are counted in /metrics as asobeast_account_mail_attempts over the last day, and mail.failures.clustered fires once a fifth of the attempts are being refused. See Hosted observability.The relay is verified once before the first message of a process, so a wrong host, port or credential fails with the relay’s own response rather than being discovered by a customer who never got their link.
OPENAI_API_KEY is unset, which disables the AI audit, the metadata drafts card and action explanations. Every other feature works without it. See Enable the optional AI features.

Still stuck?

Collect the bounded diagnostics below and open an issue with them.
Never paste the output of docker compose config into an issue. It contains the resolved database password, and with the tunnel overlay composed it also contains the Cloudflare Tunnel token, which is enough to route traffic through your tunnel.
Last modified on October 14, 2026