// Reference
JSON output, errors and exit codes
The contract every simforge command keeps - one JSON document on stdout, a structured error on stderr, and exit codes 0, 1 and 2 - so scripts and agents can rely on it.
Every simforge command keeps the same contract, so a script or an agent can drive it without parsing prose.
stdout: one JSON document#
A command prints exactly one JSON document on stdout. JSON is the default; --json asks for it explicitly, and --pretty indents the same document for people. Nothing else is ever written to stdout.
stderr: a structured error#
When a command fails it prints one JSON line on stderr:
{"code": "max_cost_required", "reason": "…", "hint": "Pass --max-cost CENTS to explicitly cap this cloud job."}codeis stable: key your handling on it. Never parsereason, which is for people.hintsays what to do next, often the exact command.pathnames the input at fault, anddetailcarries structured context, when there are any.httpStatusandrequestIdare there when the SimForge host refused a request: quote therequestIdto support, which traces the request by it.
login also writes event lines ({"event": …}, never a code) on stderr while it waits: the URL and code a person must approve. runtime install and maps pull write {"event": "distribution.download.progress", "bytes": {"done": …, "total": …}, "percent": …} lines as they download, at each tenth of the archive and at least every 30 seconds. A command that waits on a cloud run (--cloud --wait, runs watch) writes {"event": "run.progress", "runId": …, "status": …, "jobs": [{"kind", "status", "progress", "queue"}], "elapsedSeconds": …, "message": …} when it first reads the run, whenever the run or a job changes, and at least every 30 seconds.
Exit codes#
| Exit | Meaning | What to do |
|---|---|---|
| 0 | OK | Read stdout |
| 1 | The command could not run: bad flags, a missing file, the runtime or a map not installed, not signed in | Fix the invocation, or install what the error names |
| 2 | The command ran and found something wrong with its input: a failed check, a refused operation, a digest mismatch | Report or repair the input; retrying the same input gives the same answer |
The command surface as data#
simforge --help --json
simforge render --helpsimforge --help --json prints every command with its arguments and flags: types, defaults, allowed values and which ones are required. simforge <command> --help prints one command. An unknown flag is an error (unknown_flag), except after the scenario of render, simulate and preview, whose trailing arguments are runtime options: check those against the command's help. The same document is published at /docs/cli.json and rendered as the command reference.
A request the hosted API refuses (an HTTP 4xx answer, such as budget_exceeded or insufficient_scope) exits 2 with the API's own code; a server failure exits 1.
Common error codes#
| Code | Meaning |
|---|---|
unknown_command, unknown_flag | Not a command or flag of this CLI; read --help |
missing_argument, bad_value | A required argument is missing, or a value is invalid |
not_logged_in, session_invalid | Sign in with simforge login |
runtime_not_installed | Install the runtime: simforge runtime install --accept-license |
runtime_platform_unsupported | This platform has no local runtime (Windows on Arm): add --cloud |
map_not_installed | Pull the map: simforge maps pull <name>@<version> --accept-license |
agreement_acceptance_required | Read simforge runtime license, then pass --accept-license |
entitlement_required | This download is not available to your account |
entitlement_revoked | SimForge revoked this account's right to the download; it is not re-granted by accepting again |
gpu_unsupported, gpu_memory_unsupported, gpu_driver_unsupported | The GPU is outside the supported range (NVIDIA with at least 8 GiB and driver 570 or newer, or Apple M3 or newer); 2D renders, simulation and env serve --no-sensors still work |
native_gpu_out_of_memory | The scene did not fit in GPU memory: use --textures bc7-512, fewer or smaller cameras, or --cloud |
signature_missing, signature_invalid, signature_untrusted, signature_wrong_host, signature_mismatch | The download is not one SimForge signed for this host; nothing was installed |
runtime_install_invalid | The runtime found is not an installed SimForge runtime release (no runtime-manifest.json beside it): run simforge runtime install --accept-license |
recording_missing | A scenario that replays a recording cannot find recordings/<sha256>.rec.json.gz beside its document.json |
plan2d_map_missing | The map's 2D derivative is not installed: pull the map again |
max_cost_required, budget_exceeded | A cloud run needs a cost cap, or its estimate is over it |
insufficient_credits | The workspace's credits do not cover a cloud run's price |
cloud_not_open | SimForge Cloud is not open on this host yet, or does not run that work yet (detail.code run_kind_unavailable): run without --cloud |
email_unverified | Downloads and cloud runs need a verified email: open the link in your email, or resend it from the page the hint names |
file_exists | The output exists; pass --force to overwrite it |
Codes for a specific area are on its page: sign-in and runtime, cloud.