---
url: https://marimo-team.github.io/marimo-studio/reference/errors-and-json.md
description: >-
  Stable JSON result, JSON Lines progress and diagnostics, HTTP error, Python
  exception, and exit-status contracts.
---

# Errors and JSON

`--json` gives commands separate result and diagnostic channels. Keep them
separate when another program reads the result:

* Standard output contains one JSON result after a successful operation.
* Standard error contains one JSON object per progress or diagnostic line.
* The process exit status identifies the failure category.

```sh
marimo-studio status --target analysis.py --json \
  >status.json 2>diagnostics.jsonl
```

Every top-level result record has `schema: 1`. Each command's result shape
matches the `to_dict()` contract of its Python record. See [Python
API](python-api.md#public-records) for record fields.

## Diagnostic events

[JSON Lines](https://jsonlines.org/) stores one JSON object on each line, so a
caller can process diagnostics as they arrive. An event has this shape:

```json
{
  "schema": 1,
  "event": "diagnostic",
  "command": "view create",
  "severity": "info",
  "code": "next-command",
  "message": "uvx --with marimo-studio marimo edit analysis.py --sandbox --watch",
  "details": {
    "action": "edit"
  }
}
```

| Field       | Type                          | Contract                                                              |
| ----------- | ----------------------------- | --------------------------------------------------------------------- |
| `schema`    | integer                       | `1`                                                                   |
| `event`     | string                        | `diagnostic`                                                          |
| `command`   | string or `null`              | Parsed command path, such as `view build`                             |
| `severity`  | `info`, `warning`, or `error` | Diagnostic severity                                                   |
| `code`      | string                        | Stable machine-readable category                                      |
| `message`   | string                        | Human-readable description                                            |
| `exit_code` | integer, optional             | Process exit status associated with an error                          |
| `status`    | string, optional              | Operation-specific state                                              |
| `details`   | object, optional              | Structured paths, revisions, hints, recovery files, and other context |

Provider or child process output that is not a valid trusted diagnostic event
becomes a bounded `process-output` warning. Studio keeps the last 16,384
characters of that text and reports omitted character counts in `details`.

## Progress events

Static preflight and export commands stream progress on standard error. A
record has this shape:

```json
{
  "schema": 1,
  "event": "progress",
  "command": "view export",
  "progress": {
    "view": "dashboard",
    "runtime": "zero-python",
    "source": "marimo-export",
    "event": {
      "kind": "state_finished",
      "completed": 3,
      "total": 12,
      "state": "reviewed",
      "cache": {
        "authored_hits": 4,
        "authored_misses": 1,
        "projection_hits": 2,
        "projection_misses": 0
      },
      "elapsed_seconds": 0.42,
      "message": null
    }
  }
}
```

Each record includes the view, runtime, owning source, and nested event.
Events owned by `marimo-export` keep its state counts, cache activity, elapsed
time, and message unchanged. Consumers may stream, retain, or discard these
records independently of the result, which stays one JSON object on standard
output. A command that
re-enters the notebook environment relays the same progress records, separate
from process-output warnings.

## Expected command failures

An expected `MarimoStudioError` produces one error diagnostic with its stable
`code`, message, exit status, optional `hint`, optional `transient: true`, and
`diagnostic_details()` fields. Its exit status follows the
[CLI exit status](cli.md#exit-status) categories. Argument parsing errors use
code `usage-error` and exit status `2`. An interrupted confirmation or command
uses code `interrupted` and exit status `130`.

## Python error contract

Catch `MarimoStudioError` for expected failures:

```python
from marimo_studio.errors import MarimoStudioError

try:
    await view.build()
except MarimoStudioError as error:
    print(error.code, error.exit_code, error.transient)
    print(error.diagnostic_details())
```

Every expected error exposes:

| Attribute or method    | Contract                                        |
| ---------------------- | ----------------------------------------------- |
| `code`                 | Stable machine-readable category                |
| `exit_code`            | CLI exit status                                 |
| `status_code`          | HTTP status used by Studio routes               |
| `transient`            | Whether a fresh read or later retry may succeed |
| `public_hint`          | Repair action suitable for a public surface     |
| `public_message()`     | Message safe for browser routes                 |
| `diagnostic_details()` | JSON-compatible repair context                  |

### Public error classes

| Class                              | Code                                                                                                                           | Exit |                   HTTP | Recovery contract                                                       |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---: | ---------------------: | ----------------------------------------------------------------------- |
| `MarimoStudioError`                | `marimo-studio-error`                                                                                                          |  `3` |                  `500` | Base class                                                              |
| `ConfigurationError`               | `configuration-error`                                                                                                          |  `3` |                  `500` | Fix saved configuration or source                                       |
| `NotebookSourceError`              | `notebook-source-error`                                                                                                        |  `3` |                  `500` | Fix the notebook problem the message names                              |
| `ViewProjectError`                 | `view-project-error`                                                                                                           |  `3` |                  `500` | Fix the source-located provider diagnostic and rebuild                  |
| `BindingError`                     | `binding-error`                                                                                                                |  `4` |                  `500` | Select a valid cell or alias                                            |
| `ProtocolError`                    | `protocol-error`                                                                                                               |  `6` |                  `500` | Align installed Studio and marimo versions                              |
| `CapabilityInputError`             | Supplied by the caller                                                                                                         |  `2` |                  `400` | Fix the field named in `details.field`                                  |
| `RuntimeTimeoutError`              | `runtime-timeout`                                                                                                              |  `3` |                  `504` | Fix the blocking notebook operation or increase the timeout             |
| `AgentRequestError`                | Supplied by the server                                                                                                         |  `5` | Supplied by the server | Use returned details and retry classification                           |
| `DependencyError`                  | `dependency-error`                                                                                                             |  `7` |                  `500` | Repair target Python metadata or environment preparation                |
| `StaticExportError`                | `static-export-error`, `static-delivery-preflight-failed`, or a `marimo-export` `destination_*` or `export_commit_failed` code |  `3` |                  `500` | Repair the source, reference, or destination named by the diagnostic    |
| `PublicationError`                 | `zero-python-publication-error`, `zero-python-projection-*`, or the originating `marimo-export` code                           |  `3` |                  `409` | Repair the projected result or select another static runtime            |
| `PublicationUnavailableError`      | `zero-python-publication-unavailable`                                                                                          |  `3` |                  `409` | Open the view in Studio to prepare its notebook state, then retry       |
| `PublicationLimitError`            | `zero-python-state-limit`                                                                                                      |  `3` |                  `413` | Reduce the prepared state space                                         |
| `RuntimeSelectionError`            | `runtime-unavailable`                                                                                                          |  `3` |                  `400` | Select a runtime listed by the workspace                                |
| `RuntimeConfigTooLargeError`       | `runtime-config-too-large`                                                                                                     |  `3` |                  `413` | Bound projection targets or reduce notebook source                      |
| `SourceNotFoundError`              | `source-not-found`                                                                                                             |  `3` |                  `404` | Read the current Source catalog and select an authorized path           |
| `SourceEncodingError`              | `invalid-source-encoding`                                                                                                      |  `3` |                  `400` | Save the Source document as UTF-8                                       |
| `SourceValidationError`            | `invalid-source-content`                                                                                                       |  `3` |                  `400` | Repair the affected source or manifest contract                         |
| `SourceTooLargeError`              | `source-too-large`                                                                                                             |  `3` |                  `413` | Reduce the Source document size                                         |
| `SourceConflictError`              | `source-conflict`                                                                                                              |  `3` |                  `412` | Read the current revision, merge, and retry                             |
| `ViewNotFoundError`                | `view-not-found`                                                                                                               |  `3` |                  `404` | Choose an entry from `available_views`                                  |
| `ProviderNotFoundError`            | `provider-not-found`                                                                                                           |  `3` |                  `404` | Install or choose an entry from `available_providers`                   |
| `StarterNotFoundError`             | `starter-not-found`                                                                                                            |  `3` |                  `404` | Choose an entry from `available_starters`                               |
| `ViewExistsError`                  | `view-exists`                                                                                                                  |  `3` |                  `409` | Choose another name or remove the existing view first                   |
| `InvalidViewNameError`             | `invalid-view-name`                                                                                                            |  `3` |                  `400` | Choose a lowercase name that starts with a letter and is not reserved   |
| `ViewRenameError`                  | `view-rename-error`                                                                                                            |  `3` |                  `409` | Close programs that use the view project, or resolve the named error    |
| `ViewGenerationConflictError`      | `view-generation-conflict`                                                                                                     |  `3` |                  `409` | Reopen the workspace and reacquire the view                             |
| `WorkspaceGenerationConflictError` | `workspace-generation-conflict`                                                                                                |  `3` |                  `409` | Open the workspace again                                                |
| `WorkspaceMutationError`           | `workspace-mutation-incomplete`                                                                                                |  `3` |                  `409` | Inspect `recovery` and reload before retrying                           |
| `ViewDeletionError`                | `view-deletion-error`                                                                                                          |  `3` |                  `500` | Inspect `cleanup` or `recovery` before another mutation                 |
| `ViewInUseError`                   | `view-in-use`                                                                                                                  |  `3` |                  `409` | Rename or remove through the process in `details.processes`, or stop it |
| `LastViewError`                    | `last-view`                                                                                                                    |  `3` |                  `409` | Create the replacement view, then remove this one                       |
| `PublicationHeldError`             | `publication-held`                                                                                                             |  `3` |                  `409` | Release the hold named in `details.owner` or wait for it to expire      |

Generation and incomplete-mutation errors marked `transient` require a fresh
read before retry. A `configuration-error` marked `transient` reports a file
that kept changing while Studio read it, such as a notebook during repeated
saves, and the operation can be retried. `AgentRequestError` can also carry a
server-supplied retry classification.

## HTTP error responses

Studio routes encode expected errors as JSON:

```json
{
  "error": "source-conflict",
  "message": "index.html changed on disk.",
  "revision": "sha256:..."
}
```

The response status equals `error.status_code`. The `Marimo-Studio-Error`
response header repeats the code, and expected error responses use
`Cache-Control: no-store`. An available hint appears as `hint`. A retryable
failure includes `transient: true`.

Python runtime routes use two synchronization codes. `runtime-sync-pending` is
transient while the editor session applies changed cells, so the browser can
retry the request. `runtime-sync-required` is terminal for the current
notebook state. Run the changed cells in the editor, then retry the preview.

Authentication failures use route-owned codes such as
`authentication-required`, `edit-access-required`, `missing-server-token`, and
`invalid-server-token`.
