Troubleshooting
Where Openship shows you what went wrong — the build screen, the Logs tab, and the CLI — and how to read an error before you try to fix it.
When something breaks, Openship has almost always already told you why — the trick is knowing where it wrote it down. This page is the starting point: it shows you the handful of places the real answer lives, and one habit that solves most problems on its own.
The one habit that fixes most things
Whatever went wrong, scroll to the bottom of the output and read the last red lines. Openship (and the tools it runs — npm, Docker, your framework) print the actual cause right before they give up. Everything above the red is usually just normal progress.
Where the useful information lives
There are only a few screens you ever need. Match your situation to the right one:
| When... | Look here | How to open it |
|---|---|---|
| A deploy is running or just failed | The live build screen | You land on it after pressing Deploy; it streams every build step as it happens. |
| Your app is deployed but misbehaving | Project → Logs tab | Open the project, choose Logs. Two sub-tabs: Terminal (your app's own output) and Server, whose panel is titled HTTP Request Logs (incoming requests). |
| Nobody's requests are reaching the app | HTTP Request Logs | The Server sub-tab of Logs — each row is a request with its method, path, status code, and response time. |
| You work from the terminal | The CLI | openship logs <deploymentId> --follow, plus openship doctor and openship status. |
The live build screen
This is the page you watch during a deploy — like watching the oven through the glass door. It streams the build as it happens and, when it finishes, hands you the live URL. If a build fails, this is the first place to look: the failing command and its error are in the last lines before the stream stops. See the deploy wizard for a tour of it.
The project Logs tab
Once an app is live, open it and pick Logs. You get two sub-tabs you switch between:
- Server — its panel is headed HTTP Request Logs: one line per incoming request (method, path, status
code, response time, country, and size). Great for "is anything even hitting my app?" and for spotting a
flood of
4xx/5xxresponses. (For a static site with no runtime, this tab is relabeled Requests.) - Terminal — your app's own stdout/stderr, streamed straight from the running container. This is where a crash, a stack trace, or a "listening on port…" line shows up.
Use the Copy or Download buttons in the header row to grab the logs when you want to save them or ask for help. The full walkthrough is in Logs & monitoring.
The Logs tab says it can't connect
If the live terminal pops up "Failed to connect to terminal logs, make sure your project is running", or the HTTP Request Logs panel shows "Connection to log stream lost", the app isn't currently running (or was put to sleep). Redeploy it, or wake it, and the live tail reconnects on its own. In the terminal, "Waiting for logs…" just means it's connected but the app hasn't printed anything yet — that's normal for a quiet app.
The CLI
Everything above has a terminal equivalent:
# Snapshot of a deployment's logs
openship logs <deploymentId>
# Stream them live until the deployment finishes
openship logs <deploymentId> --follow
# Just the last 50 lines
openship logs <deploymentId> --tail 50Two commands answer "is my setup even OK?" before you go hunting further:
# Check config, active login, whether the API is reachable, and your runtime
openship doctor
# Health + mode (self-hosted vs cloud) of the API you're pointed at
openship statusopenship doctor prints a checklist with a green ✓, yellow !, or red ✗ next to each of config,
context, api, node, and bun — so a red line tells you exactly which part is wrong. Full
command details live in the CLI reference.
How to read an Openship error
Openship errors are short and structured on purpose — they're not meant to be scary.
In the dashboard, failures show up as a toast (a small popup) with a message, and — for anything that was streaming — as a red line in the build screen or Logs terminal. Read the message; it's the same text the server sent.
From the API or CLI, every error comes back as a small JSON object with two fields you care about:
{ "error": "human-readable message", "code": "MACHINE_CODE" }erroris the sentence to read.codeis a stable label you can search for. Bad input is reported ascode: "VALIDATION_ERROR"with adetailsobject naming the exact fields that failed.- The HTTP status tells you the category at a glance:
400bad request,401not logged in,403not allowed,404not found,409conflict (something already exists / is in use),500a genuine server error. A bare{ "error": "Internal server error" }with status500means the cause is in the server logs, not in what you sent.
Symptom: a deploy failed and you can't tell why
The build stopped with a red error and no obvious explanation
The build screen (or openship logs <id> --follow) ends on red lines instead of a live URL.
What it means — a command in the build gave up. The line that matters is the last one before the stream stopped, not the wall of output above it.
How to fix
- Scroll to the bottom of the build screen and read the final red lines out loud — they name the failing step (a missing command, a package that won't install, a port mismatch).
- If it mentions a missing setting or secret, add it under the project's Configuration tab and redeploy.
- Still stuck? Press Copy/Download to save the log, then match the message against Troubleshooting → Deployments, which lists the common build and runtime failures with fixes.
Symptom: the CLI can't reach your instance
"Cannot reach the API at …" or a red ✗ next to "api" in openship doctor
Commands hang or fail before doing anything, and openship doctor reports the api check as unreachable
or an unexpected HTTP status.
What it means — the CLI is pointed at an instance it can't talk to: the wrong address, an instance that isn't running, or a login that has expired.
How to fix
- Run
openship doctor. It checks, in order: your config file, your active context and token, and whether the api answers. - If context is yellow with "has no token; run
openship login", log in again. - If api is red, confirm the instance is actually up (
openship statusshows its health and mode) and that the address is the one you expect.
Symptom: openship up refuses to regenerate secrets
"Refusing to continue: this would regenerate secrets your existing install already has"
A re-run of openship up (Compose install) exits without starting anything and names one or more of
POSTGRES_PASSWORD, BETTER_AUTH_SECRET, INTERNAL_TOKEN.
What it means — those secrets are generated once and stored only in ~/.openship/compose/.env. This run
couldn't read them there, but the install's database volume is still on the box. Regenerating them cannot work:
Postgres applies POSTGRES_PASSWORD only when it first creates its data directory (the API would fail with
password authentication failed for user "openship"), and BETTER_AUTH_SECRET is the key your stored
environment variables are encrypted with. So the run stops before writing anything rather than leaving you
with a stack that can't start.
How to fix
- Check who you're running as.
sudo openship upreads/root/.openship/compose/.env; withoutsudoit reads the one in your own home. Re-run as the user that owns the install. - If the file is there but unreadable, fix its permissions — don't let the secrets be regenerated instead.
- If it was overwritten, restore it. Every
openship upkeeps the.envit replaced at~/.openship/compose/.env.bak; older values may also survive in a stopped container (docker inspect <container> --format '{{json .Config.Env}}'). - Only if the original values are genuinely gone:
openship up --reset-secrets. The database password is realigned for you, but every stored environment variable becomes permanently unreadable — you'll need to re-enter them under each project's Configuration tab.
Preview it first
openship up --dry-run lists each secret as <preserved> or <generated on this run> and warns when a real run
would refuse — so you can check what a re-run will do before it touches the box.
Symptom: the openship command crashes, or vanishes after a Node upgrade
"SyntaxError: Invalid regular expression flags" — or "openship: command not found" right after installing
npm i -g openship reported success, but the command either dies instantly with a SyntaxError
pointing at a file you've never heard of (string-width, commander) or isn't on your PATH at all.
What it means — a package-manager install runs on your Node, and Openship needs Node 22+. On Node 18 the install genuinely succeeds and the binary is linked; it's the first dependency it loads that can't be parsed by that Node.
Current CLI versions handle this for you: instead of the SyntaxError they offer to download an
official Node 22 into ~/.openship/runtime and use it for Openship only. So a raw SyntaxError means
you're on an older release — reinstall the CLI and it will offer the fix.
The command not found variant usually follows fixing the first one: nvm, fnm and volta keep global
packages per Node version, so installing a newer Node leaves the CLI behind with the old one.
How to fix
- Check what you're on:
node --version. Below 22, either accept the CLI's offer to fetch its own Node, upgrade yourself, or skip the question entirely withcurl -fsSL https://get.openship.io | sh— that installer never touches the Node you have. - Scripting it?
OPENSHIP_VENDOR_NODE=1accepts the download without a prompt (0declines). - After upgrading Node with a version manager, reinstall the CLI on the new version:
npm i -g openship. - Still not found? The official installer puts it in
~/.openship/bin— open a new terminal, orexport PATH="$HOME/.openship/bin:$PATH".
Jump to the right page
Deployment & build failures
Build went red, wrong port, missing env var, app won't start — the common deploy failures and their fixes.
GitHub connection & repos
Expired connection, a private repo that won't import, auto-deploy webhooks that never fire.
Domains, DNS & SSL
A custom domain that won't verify, DNS that hasn't propagated, a certificate stuck provisioning.
Servers & SSH
A server that won't connect over SSH, a component that won't install, missing Docker, port-forward tunnels.
Host control channel
"This operation targets the HOST machine, but no host channel is configured" — the repair, per install shape.
Desktop app & local data
Startup problems, the database lock, a stuck update, and where your local data lives.
Common errors
The API error codes and messages you'll actually hit — what each one means and how to fix it.
Authentication
How you prove who you are to Openship — session cookies, personal access tokens, MCP OAuth, and desktop loopback mode.
Deployment & build failures
The build went red — here's how to read the failure and fix the usual causes, from a wrong build command to a compose deploy that needs a decision.