Skip to main content
Every fallible call returns lager::Result<T>, an alias for std::result::Result<T, lager::Error>.
Error is #[non_exhaustive], so a match on it needs a catch-all arm and new variants will not break your build.

Variants

Variant Reference

Connection(String)

The crate did not reach the box at all. This variant also covers a failed Socket.IO connect.

Timeout(String)

A client-side deadline expired: the HTTP request, a streaming session’s connect confirmation, or a wait_for needle that never arrived.
A hardware wait that expires is not this variant. wait_for_level timing out on the box comes back as Error::Box with HTTP 502 and GPIO 'gpio24' did not reach level 1 within 2.0s, because the box completed the request and reported the outcome. Error::Timeout means the transport gave up.

Box { status: u16, message: String }

The box accepted the request and reported a failure. This is the variant you will see most, and the message is the box’s own text.
Common shapes: A router net’s “not found” reads Net 'router1' not found with no role, because router nets deliberately send no role hint. The box can also report failure with HTTP 200 and success: false — a cross-role instrument conflict does this. That is still Error::Box.

UnsupportedByBox { message }

The endpoint exists in the API, but this box is too old to serve it. The message names the version needed.
Examples: erase_range() and halt() check the debug service’s features before they send anything. So an old box fails with this variant before it touches the target.

NotSupportedByBox { feature, details }

The crate has no route for this feature on any box. Since crate 0.8, no net type returns it: Scope was the last stub. The variant stays, so a match on it still compiles.
UnsupportedByBox and NotSupportedByBox are different variants with confusingly similar names. Unsupported means update the box. Not supported means no box can do this yet.

DfuFailed { status, exit_code, stdout, stderr }

Box-side dfu-util ran and exited non-zero (HTTP 502 from POST /usb/dfu). Both output streams are complete, and the message quotes both. dfu-util reports some device failures on stdout, and its suffix warnings on stderr.

FlashFailed { error, output }

A debug flash ran but programmed nothing. The box answers HTTP 200 with programmed: false for this (box 0.51.0 and later). error is the box’s verdict line, and output is the backend’s output.

ProbeBusy { message }

Another operation, such as a flash or an erase, held the debug probe for longer than the box waits (HTTP 503 from the debug service). Retry when the other operation is done.

SafetyRefused { message }

The net is configured with allow_destructive: false, and the debug service refused a flash or an erase (HTTP 403).

Decode(String)

The crate did not parse the response into the expected shape. The cause is a truncated body, an unexpected field type, or a missing required field.

AuthRequired { box_host, auth_url, message }

A gated box, and no usable credential.
See Authentication.

Config(String)

A client-side problem, detected before anything is sent: LAGER_BOX_HOST unset, an unparseable host, a firmware path whose type cannot be inferred, an unreadable file.

Stream(String)

A UART or RTT session failed: the net is already in use by another session, the device disappeared, or the session closed unexpectedly.

Matching

Skipping a test on an old box

Notes

  • Error implements std::error::Error and Display, so ? works into Box<dyn Error> and anyhow::Error without a conversion.
  • From<serde_json::Error> maps into Error::Decode.
  • The messages are written to be read by a person in CI output. Print the error rather than only its variant.