MidstreamDocs
When something goes wrong

Reading a deploy's timeline

Find the deploy that failed, see which phase it died in, read what your own commands printed, and retry it.

Every deploy records what it did, phase by phase, with how long each phase took and what the failure was. This page shows you how to read that record and get from "the instance won't open" to "the install command is broken" in about thirty seconds.

Finding a deploy

Open the project and choose Deploy health in the sidebar.

The top of the page answers "is this normal?" — the share of deploys that succeeded, how long an average deploy takes, and how many failed in the last thirty days, with a chart of deploys per day. Under that, Unhealthy scenes lists the scenes that have failed recently, so a scene that is broken for everyone stands out from a one-off blip.

Deploys below that is the full list: every deploy, newest first, grouped by day. Each row carries the scene name, the test file it runs, the error code if it failed, when it started, and how long it took. Filter to Failed, In flight, or Ready with the buttons above the list.

A deploy in flight updates on its own — leave the page open and watch it move.

The phase timeline

Open a deploy to see the phases it went through:

PhaseWhat happens
BootThe container your app runs in starts up and reports for duty.
Clone repoWe fetch your repository at the capture's commit.
Build planWe read midstream.json and work out what to run.
InstallYour install command runs.
Install browserWe make sure the container has the Chromium build your Playwright version asks for.
Start appYour start command runs, and we wait for the app to answer on its port.
Run test to sceneYour test runs and stops at the scene, and we capture the session there.

Each phase shows one of these states:

  • A duration — it finished, and that is how long it took.
  • cached — it was skipped, because an earlier deploy of this instance already did the work. Resumed instances often skip the clone and the install, which is why a second open is so much faster than the first.
  • not needed — only on the browser step, and only for a project with no Playwright of its own in the container. There was no browser to install.
  • Spinning, with a running clock — it is happening now.
  • failed after… — it died here. The error opens inline underneath.
  • — it never ran, because something before it failed.

The phases run in that order, and a deploy stops at the first one that fails, so the timeline reads as one story: everything above the failure worked, nothing below it was attempted.

The error

Under the phase that failed you get five things:

  • The code, such as SANDBOX_INSTALL_FAILED. Every code is listed in Why a deploy failed.
  • Whose side it is on — "project issue" or "midstream infra".
  • Whether it is transient, meaning a retry has a real chance of working.
  • The command it ran, verbatim from your midstream.json. "The start step failed" tells you which phase; ./scripts/start.sh tells you which file to open.
  • The raw output from that command.

A deploy that ran out of time gets one more line: the budget it ran out of, and the one every project gets. "Failed after 3m 0s" is not much on its own — the point is that the 3m is ours, not your test's, and a project that legitimately needs longer can be given more. See Time limits.

Command output

Every phase that runs a command from your midstream.json keeps what that command printed, under Command output on the phase itself. The phase that failed opens by default; the others fold away.

Three things worth knowing about it:

  • It arrives while the command is still running. A deploy you open mid-flight streams its output into the page. This is the point: a start command that hangs never finishes, so waiting for it to finish would show you nothing in exactly the case you most need to see.
  • Successful phases keep their output too. The warning that explains a failure is often printed by the step before it.
  • A very long log keeps its end, not its beginning. If a command prints more than we store, we drop from the front and say how much — the end is where the failure is.

Output is shown to workspace members only. Someone who opened an instance link sees a short message and nothing else — no commands, no output, no stack traces.

Reading it without the page

The same output is available over the API, so you can point an agent at a failing deploy instead of copying text out of a browser:

curl -H "Authorization: Bearer $MIDSTREAM_API_KEY" \
  "https://midstream.studio/api/v1/instances/deploys/$DEPLOY_ID/logs"

You get one entry per step, each with the step name, its output, and whether the log was cut. Deploy ids come from /api/v1/instances/deploys?workspaceSlug=…&projectSlug=…, which also carries each deploy's error code and the command that failed. The error codes are stable and enumerable — the catalog is the full list — so an agent can branch on the code rather than parse a message.

Running the test locally

Each deploy also records exactly what it was trying to run: the test file, the chain of test titles within it, and the commit. Alongside them:

npx midstream your-scene-slug

Be clear about what that does and does not do. It finds the test containing the scene and runs it headed against an app you are already running, pausing at the scene. It does not run your install or start command, and it does not start from a cold container — so it is the right tool for a test that stops short of the scene, and the wrong one for an install or start command that fails. For those, the command output above is the reproduction.

Retrying

If the deploy failed, Retry provision at the top of the page starts a fresh one against the same capture. The failed deploy stays in the list — the history is the point, so "it failed twice and then worked" remains answerable.

You cannot retry a deploy that is still in flight or one that succeeded. Wait for it, or reset the instance from its toolbar.

Retrying requires workspace membership.