Skip to main content
Sometimes logs and metrics aren’t enough and you need to look inside a live runner — inspect the filesystem, check GPU utilization, or verify that model weights downloaded correctly. The fal runners CLI gives you direct access to any running container. First, find the runner you want to inspect:
Then either open an interactive shell or run a one-off command.

Interactive shell

fal runners shell opens an interactive session inside the runner’s container, giving you full shell access to explore:
Press Ctrl+D or type exit to disconnect. Use this for exploratory debugging sessions where you don’t know exactly what you’re looking for yet.

One-off commands

fal runners exec runs a single command on the runner without opening a shell. Pass the command after a -- separator so its arguments aren’t parsed as fal CLI flags:
Use exec for quick checks or scripted inspection; add -it when the command needs a TTY and stdin, like a REPL. Both commands attach to the runner’s container environment, so anything your app can see — environment variables, mounted persistent storage, GPU devices — is available to you.

Termination Reasons

When a runner begins shutting down, the dashboard shows a termination reason next to its state. Hover over the reason for a short explanation. Some reasons describe normal lifecycle activity, while others indicate an app or infrastructure problem that may need investigation. The termination reason describes why the runner stopped. It does not, by itself, tell you whether a request was retried or which HTTP status code the caller received. A runner can stop after a request completed successfully, while a failed request can be retried on a different runner. See Termination reasons, request outcomes, and retries below for how these signals relate. New or unrecognized reasons are shown as received, with a generic explanation, so future backend values remain visible instead of being hidden.

Termination reasons, request outcomes, and retries

A termination reason is recorded on a runner, while status codes, error types, and retry decisions belong to individual requests. There is not a one-to-one mapping between them:
  • A normal lifecycle reason such as Keep-alive expired, Deployment rollout, or Scaled down usually happens after active work has finished and does not change a completed request.
  • A failure reason such as Runner crashed, Connection errors, or Request timed out can identify why an attempt failed, but the request interface and retry configuration determine what happens next.
  • A single runner can process many requests. The reason shown when it eventually stops does not describe every request that ran on it.
  • Queue retries run the next attempt on another runner. Direct run() and stream() calls are not automatically retried.

Application response codes

Your endpoint’s response code can affect both the current request and whether fal keeps the runner alive. The resulting termination label records the runner cleanup decision, not the response itself. Response headers can decouple these decisions. X-Fal-Needs-Retry controls whether the request is retried, while x-fal-stop-runner controls whether the runner is stopped. Therefore, neither the response code nor the termination reason alone is enough to reconstruct both decisions.

Platform failures

When fal detects a failure before receiving a usable endpoint response, the request interface determines the caller-visible result: For the complete retry controls, retry budgets, and response header behavior, see Retries and Error Handling. To correlate a failed request with a runner, inspect the response’s error_type field or X-Fal-Error-Type header and see Request Error Types.

Understanding Runners

What runners are, their lifecycle states, and how they start and shut down

CLI: fal runners

Full reference for list, logs, stop, kill, shell, and exec