# XO0540: a Mutex.with write that an Err undoes

A `Mutex.with` closure's changes to its `var` value are written back only when it returns successfully; an Err (a `return Err(...)`, a `?`, or a call that can fail as the closure's result) leaves the protected value as it was. A sticky error, a `done` flag, or consumed input stored before the failure is lost with it. To keep the change and still report the failure, return the outcome as the closure's success value (its type `Result[T, E]` with no `!`) and apply `?` outside the `with`.

## Example

```xo
fn fail(m: Mutex[St], e: E) -> () ! E {
  m.with(fn(var st) -> () ! E {
    st.err = Some(e)
    Err(e)
  })
}
```

## Fix

```xo
fn fail(m: Mutex[St], e: E) -> () ! E {
  let r = m.with(fn(var st) -> Result[(), E] {
    st.err = Some(e)
    Err(e)
  })
  r?
}
```

Run `xo explain XO0540` for this text in a terminal, or see
[section 10.6 of the specification](../../spec/core/#106-diagnostic-codes).

