Troubleshooting

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 hereHow to open it
A deploy is running or just failedThe live build screenYou land on it after pressing Deploy; it streams every build step as it happens.
Your app is deployed but misbehavingProject → Logs tabOpen 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 appHTTP Request LogsThe Server sub-tab of Logs — each row is a request with its method, path, status code, and response time.
You work from the terminalThe CLIopenship 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/5xx responses. (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 50

Two 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 status

openship 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" }
  • error is the sentence to read.
  • code is a stable label you can search for. Bad input is reported as code: "VALIDATION_ERROR" with a details object naming the exact fields that failed.
  • The HTTP status tells you the category at a glance: 400 bad request, 401 not logged in, 403 not allowed, 404 not found, 409 conflict (something already exists / is in use), 500 a genuine server error. A bare { "error": "Internal server error" } with status 500 means 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

  1. 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).
  2. If it mentions a missing setting or secret, add it under the project's Configuration tab and redeploy.
  3. 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

  1. Run openship doctor. It checks, in order: your config file, your active context and token, and whether the api answers.
  2. If context is yellow with "has no token; run openship login", log in again.
  3. If api is red, confirm the instance is actually up (openship status shows 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

  1. Check who you're running as. sudo openship up reads /root/.openship/compose/.env; without sudo it reads the one in your own home. Re-run as the user that owns the install.
  2. If the file is there but unreadable, fix its permissions — don't let the secrets be regenerated instead.
  3. If it was overwritten, restore it. Every openship up keeps the .env it replaced at ~/.openship/compose/.env.bak; older values may also survive in a stopped container (docker inspect <container> --format '{{json .Config.Env}}').
  4. 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

  1. 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 with curl -fsSL https://get.openship.io | sh — that installer never touches the Node you have.
  2. Scripting it? OPENSHIP_VENDOR_NODE=1 accepts the download without a prompt (0 declines).
  3. After upgrading Node with a version manager, reinstall the CLI on the new version: npm i -g openship.
  4. Still not found? The official installer puts it in ~/.openship/bin — open a new terminal, or export PATH="$HOME/.openship/bin:$PATH".

Jump to the right page

On this page