---
url: https://masyaka.github.io/injecute/errors/undo-failed.md
description: A lifecycle hook could not be undone
---

# `INJECUTE_UNDO_FAILED`

**A lifecycle hook could not be undone.**

## How to fix it

Its undo function threw, rejected, or did not finish before the stop signal aborted. The hook is in `path`, the original error in `cause`.

## Where you see it

`running.stop()` runs every undo function, even when some fail, then rejects with
`INJECUTE_DISPOSE_FAILED`. Each failed undo is an `INJECUTE_UNDO_FAILED` in `cause.errors`, with the hook
in `path`:

```ts
try {
  await running.stop({ signal: AbortSignal.timeout(25_000) });
} catch (error) {
  for (const failure of (error as InjecuteError).cause.errors) {
    if (failure.code === 'INJECUTE_UNDO_FAILED') {
      console.error(failure.path[0], failure.cause); // which hook, and why
    }
  }
}
```

After a failed start, the rollback reports them to `onError` with `during: 'rollback'`. An undo that
"did not finish before the signal aborted" keeps running in the background. See
[Startup and shutdown](../guide/startup-shutdown.md#timeouts-and-cancellation).

## Handling it in code

```ts
import { InjecuteError } from 'injecute';

try {
  // ...
} catch (error) {
  if (error instanceof InjecuteError && error.code === 'INJECUTE_UNDO_FAILED') {
    // error.message explains what happened; error.path is the resolution chain
  }
}
```

[All error codes](./index.md)
