Skip to content

Errors and JSON

--json gives commands separate result and diagnostic channels:

  • 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.

Keep the streams separate when another program reads the result.

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

Every top-level result record has schema: 1. The command-specific result shape matches the to_dict() contract of its Python record. See Python API for record fields.

Diagnostic events

JSON Lines stores one JSON object on each line, so a caller can process diagnostics as they arrive. One 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",
  "details": {
    "action": "edit"
  }
}
FieldTypeContract
schemainteger1
eventstringdiagnostic
commandstring or nullParsed command path, such as view build
severityinfo, warning, or errorDiagnostic severity
codestringStable machine-readable category
messagestringHuman-readable description
exit_codeinteger, optionalProcess exit status associated with an error
statusstring, optionalOperation-specific state
detailsobject, optionalStructured paths, revisions, hints, recovery files, and other context

Output from a provider or child process that is not a valid trusted diagnostic event becomes a bounded process-output warning. Studio retains at most the last 16,384 characters of that text and reports omitted character counts in details.

Progress events

Long-running static preflight and export commands stream progress on standard error. One JSON Lines 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
    }
  }
}

Consumers may render, retain, or discard these records. The successful terminal result remains one JSON object on standard output. A re-entered notebook environment relays the same progress records instead of folding them into 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.

Click argument errors use code usage-error and exit status 2. An interrupted confirmation or command uses code interrupted and exit status 130.

ExitCategory
0Operation completed
1Validation or a named provider availability check failed
2Arguments or capability input are invalid
3Configuration, source, build, export, or mutation state failed
4Cell alias binding failed
5A live Studio request failed
6Studio and Marimo protocol contracts disagree
7The target Python environment could not be prepared
130The command was interrupted

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 methodContract
codeStable machine-readable category
exit_codeCLI exit status
status_codeHTTP status used by Studio routes
transientWhether a fresh read or later retry may succeed
public_hintRepair action suitable for a public surface
public_message()Message safe for browser routes
diagnostic_details()JSON-compatible repair context

Public error classes

ClassCodeExitHTTPRecovery contract
MarimoStudioErrormarimo-studio-error3500Base class
ConfigurationErrorconfiguration-error3500Fix saved configuration or source
NotebookSourceErrornotebook-source-error3500Fix and save the highlighted Marimo cell
ViewProjectErrorview-project-error3500Fix the source-located provider diagnostic and rebuild
BindingErrorbinding-error4500Select a valid cell or alias
ProtocolErrorprotocol-error6500Align installed Studio and Marimo versions
CapabilityInputErrorSupplied by the caller2400Fix the field named in details.field
RuntimeTimeoutErrorruntime-timeout3504Fix the blocking notebook operation or increase the timeout
AgentRequestErrorSupplied by the server5Supplied by the serverUse returned details and retry classification
DependencyErrordependency-error7500Repair target Python metadata or environment preparation
StaticExportErrorstatic-export-error, static-delivery-preflight-failed, or a marimo-export destination_* or export_commit_failed code3500Repair the source, reference, or destination named by the diagnostic
PublicationErrorzero-python-publication-error, zero-python-projection-*, or the originating marimo-export code3409Repair the projected result or select another static runtime
PublicationUnavailableErrorzero-python-publication-unavailable3409Prepare the selected Zero-Python view and retry
PublicationLimitErrorzero-python-state-limit3413Reduce the prepared state space
RuntimeSelectionErrorruntime-unavailable3400Select a runtime listed by the workspace
RuntimeConfigTooLargeErrorruntime-config-too-large3413Bound projection targets or reduce notebook source
SourceNotFoundErrorsource-not-found3404Read the current Source catalog and select an authorized path
SourceEncodingErrorinvalid-source-encoding3400Save the source document as UTF-8
SourceValidationErrorinvalid-source-content3400Repair the affected source or manifest contract
SourceTooLargeErrorsource-too-large3413Reduce the source document size
SourceConflictErrorsource-conflict3412Read the current revision, merge, and retry
ViewNotFoundErrorview-not-found3404Choose an entry from available_views
ProviderNotFoundErrorprovider-not-found3404Install or choose an entry from available_providers
ViewExistsErrorview-exists3409Choose another name or remove the existing view first
ViewGenerationConflictErrorview-generation-conflict3409Reopen the workspace and reacquire the view
WorkspaceGenerationConflictErrorworkspace-generation-conflict3409Open the workspace again
WorkspaceMutationErrorworkspace-mutation-incomplete3409Inspect recovery and reload before retrying
ViewDeletionErrorview-deletion-error3500Inspect cleanup or recovery before another mutation
ViewInUseErrorview-in-use3409Close artifact readers and retry removal
LastViewErrorlast-view3409Keep one configured view

Generation and incomplete-mutation errors marked transient require a fresh read before retry. 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. Marimo-Studio-Error repeats the code in a response header, and expected error responses use Cache-Control: no-store. An available hint appears as hint. A retryable failure includes transient: true.

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