---
title: ExecResult
description: "An exec's phase and, once it has one, its outcome."
---

```python
@final
class ExecResult
```

An exec's phase and, once it has one, its outcome.

`stdout` and `stderr` are `str` because the daemon's `Outcome` carries them as strings
— the protocol crate's shape, not a choice made here. `exit_code` and `signal` are
`None` rather than sentinel integers, which is the same distinction `models.py` makes:
a signal death has no exit code, and zero is not "no signal".

## Constructor

`ExecResult` declares no `__new__` or `__init__`, so it is not constructed directly: an instance comes back from another call in this package.

## Properties

### `done`

```python
done: bool
```

Whether the exec has finished, whichever way.

### `exec_id`

```python
exec_id: str
```

### `exit_code`

```python
exit_code: int | None
```

`None` when the child died to a signal rather than exiting.

### `notes`

```python
notes: list[str]
```

Human-readable annotations, one per condition that changes how the output reads
(BIND-7): truncation at the output cap, an expired deadline, writers left alive, a
synthesized result. Empty for a clean result; append them to stderr as they are.

### `ok`

```python
ok: bool
```

Whether the command exited zero. False for a signal death and for a still-running
exec, since neither is a success.

### `phase`

```python
phase: str
```

`"running"`, `"exited"`, or `"acked"`.

### `posix_exit_code`

```python
posix_exit_code: int | None
```

The exit code a POSIX shell would report (BIND-6): 124 when a deadline ended the
command (the daemon's, or `run_to_completion`'s client deadline), 128 plus the signal
for any other signal death, otherwise `exit_code`. `None` only for a running exec.

### `signal`

```python
signal: int | None
```

The signal that killed the child, when one did.

### `stderr`

```python
stderr: str
```

### `stdout`

```python
stdout: str
```

### `synthesized`

```python
synthesized: bool
```

True when `run_to_completion` synthesized this result because nothing came back
after its client-deadline kill (BIND-10): `posix_exit_code` is 124 and the output is
unknown, not empty.

### `timed_out`

```python
timed_out: bool
```

True when the daemon execution deadline expired, distinct from cancellation.

### `truncated`

```python
truncated: bool
```

Set when either stream hit the output cap and was cut. A flag rather than a
sentinel inside the bytes, which would be indistinguishable from output that
happens to contain it.

### `writers_may_be_alive`

```python
writers_may_be_alive: bool
```

Set when the post-exit linger deadline expired with the pipes still open: some
grandchild is alive and may write more that nobody will see.

## Special methods

### `__repr__`

```python
def __repr__() -> str
```

## Provenance

This page is generated from `bindings/microvms-py/microvms.pyi` by Griffe 2.3.0, run from `site/scripts/gen-reference.mjs` on every `pnpm run sync`, so an edit made here is overwritten by the next run.

To change the page, change the doc comment in the binding's Rust source, then regenerate the declarations with `mise run stubs`. `mise run stubs:check` fails when the committed file no longer matches the source.