---
title: <TryCatchFinally>
description: Workflow-scoped error boundary with catch handlers and guaranteed cleanup.
---

```ts
import { TryCatchFinally } from "smithers-orchestrator";

type TryCatchFinallyProps = {
  id?: string;
  try: ReactElement;
  catch?: ReactElement | ((error: SmithersError) => ReactElement);
  catchErrors?: SmithersErrorCode[]; // restrict which codes trigger catch
  finally?: ReactElement; // always runs after try or catch
  skipIf?: boolean;
};
```

```tsx
<Workflow name="safe-deploy">
  <TryCatchFinally
    try={
      <Sequence>
        <Task id="build" output={outputs.build} agent={buildAgent}>Build the project.</Task>
        <Task id="deploy" output={outputs.deploy} agent={deployAgent}>Deploy to production.</Task>
      </Sequence>
    }
    catch={(error) => (
      <Task id="recover" output={outputs.recover} agent={recoveryAgent}>
        {`Recover from ${error.code}: ${error.summary}`}
      </Task>
    )}
    finally={
      <Task id="cleanup" output={outputs.cleanup}>{{ cleanedUp: true }}</Task>
    }
  />
</Workflow>
```

## Notes

- `try` takes one `ReactElement`; wrap multiples in `<Sequence>` or `<Parallel>`.
- `finally` runs even if `catch` fails.
- Unmatched `catchErrors` propagate to outer boundaries.
