[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [Task](https://evolu.dev/docs/api-reference/common/Task) › unabortableMask

```ts
function unabortableMask<T, E, D>(
  fn: (
    restore: <T2, E2, D2>(task: Task<T2, E2, D2>) => Task<T2, E2, D2>,
  ) => Task<T, E, D>,
): Task<T, E, D>;
```

Defined in: [packages/common/src/Task.ts:5184](https://github.com/evoluhq/evolu/blob/037c390af081e9944d616ff298a729515c5c5ab7/packages/common/src/Task.ts#L5184)

Like [unabortable](https://evolu.dev/docs/api-reference/common/Task/variables/unabortable), but provides `restore` for child [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task)s that
should run with the previous abort mask.

Use this for acquire/use/release flows where acquire and release must finish
once started, while use should remain abortable. Child Tasks inherit the mask
unless they are wrapped with `restore()` before scheduling.

An abort request before the mask Task starts prevents entering the mask. Once
the body starts, plain child Tasks inherit the mask, so acquire and release
can run after abort. Start release Tasks directly in the original mask's
`finally`; do not wrap release in a nested `unabortableMask`, which is a new
critical-section entry and may not start after abort.

[AsyncDisposableStack](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncDisposableStack) is often enough for ordinary acquire/release. Use
it inside `unabortableMask` when masked acquire/release spans multiple or
conditional resources.

### Example

```ts
import {
  assertEqual,
  assertFalse,
  assertTrue,
  AbortError,
  createRun,
  ok,
  unabortableMask,
  waitForAbort,
  type Task,
} from "@evolu/common";

interface Resource {
  readonly id: string;
}

const acquire: Task<Resource> = () => ok({ id: "resource-1" });
const operationStarted = Promise.withResolvers<void>();
const operate =
  (resource: Resource): Task<never> =>
  (run) => {
    assertEqual(resource.id, "resource-1");
    operationStarted.resolve();
    return run(waitForAbort);
  };
let released = false;
const release =
  (_resource: Resource): Task<void> =>
  (run) => {
    // Release inherits the mask even after abort was requested.
    assertFalse(run.signal.aborted);
    released = true;
    return ok();
  };

await using run = createRun();
const fiber = run.abortable(
  unabortableMask((restore) => async (run) => {
    // Acquire with abort masked.
    const resource = await run.ok(acquire);

    try {
      // Use with the previous abort mask restored.
      return await run(restore(operate(resource)));
    } finally {
      // Release with abort masked.
      await run.ok(release(resource));
    }
  }),
);

await operationStarted.promise;
fiber.abort();
const result = await fiber;
assertFalse(result.ok);
assertTrue(AbortError.is(result.error));
assertTrue(released);
```