--- name: try signatures: - 'try BLOCK catch (VAR) BLOCK' - 'try BLOCK catch (VAR) BLOCK finally BLOCK' since: 5.34 status: documented categories: ["Control flow"] --- ```{index} single: try; Perl built-in ``` *[Control flow](../perlfunc-by-category)* # try Run a block and divert any exception it throws into a `catch` block, with an optional `finally` block that always runs on the way out. `try`/`catch` is Perl's structured exception-handling syntax. The `try` block executes; if any statement in it throws (via [`die`](die), an uncaught exception from a callee, or a runtime error), control transfers to the `catch` block with the exception value bound to the parenthesised lexical. If nothing throws, the `catch` block is skipped. Unlike [`eval`](eval), a `return` inside `try` returns from the enclosing sub, not from the block — `try` is control flow, not a call frame. The syntax must be enabled with a feature guard: ```perl use feature 'try'; ``` ## Synopsis ```perl try BLOCK catch (VAR) BLOCK try BLOCK catch (VAR) BLOCK finally BLOCK ``` ## What you get back `try` is a statement, not an expression, but it yields the last evaluated value of whichever branch ran — the `try` block on success, or the `catch` block on failure. Used as the final statement of a sub or a [`do`](do) block, that value becomes the result: ```perl my $value = do { try { fetch_thing(@args); } catch ($e) { warn "fetch failed: $e"; $DEFAULT; } }; ``` Do **not** write `return` inside a `try` that is being used this way — `return` exits the enclosing sub, bypassing the assignment. A `finally` block's final expression is discarded; it cannot contribute to the value. ## Global state it touches - [`$@`](../perlvar) is **not** the mechanism here. `try`/`catch` binds the exception to the lexical named in `catch (VAR)`, not to [`$@`](../perlvar). Code inside `catch` sees whatever [`$@`](../perlvar) happened to hold before the `try`; rely on the lexical. - [`$_`](../perlvar), [`$!`](../perlvar), and other dynamic globals are untouched by the construct itself — only by whatever code runs inside the blocks. ## The `catch` variable `catch` must be followed immediately by a parenthesised variable declaration. `my` is implicit — write `catch ($e)`, not `catch (my $e)`. The variable is lexical to the `catch` block and holds the thrown value exactly as [`die`](die) delivered it: a string, a blessed reference, or any scalar: ```perl try { risky(); } catch ($e) { if (ref $e && $e->isa('My::Exception')) { $e->rethrow if $e->is_fatal; warn $e->message; } else { warn "plain die: $e"; } } ``` There is no multi-`catch` dispatch on exception class — write the classification yourself inside the single `catch` block. ## `finally` An optional third block runs on every exit path from the `try`/`catch` construct: normal fall-through, exception caught by `catch`, exception rethrown from `catch`, or a non-local transfer ([`return`](return), [`last`](last), [`next`](next), [`redo`](redo), [`goto`](goto)) out of either block. ```perl try { open_resource(); use_resource(); } catch ($e) { warn "failed: $e"; } finally { close_resource(); } ``` `finally` is the right place for release code that must run no matter how the protected section exits — file handles, locks, restoring global state. A `finally` block has restrictions the other two blocks do not: - No [`return`](return), no [`goto`](goto), no [`last`](last) / [`next`](next) / [`redo`](redo). Attempting any of these is a compile-time or runtime error. - The final expression value is ignored — `finally` cannot contribute to the construct's yielded value. `finally` remains **experimental** in Perl 5.42 and emits a warning in the `experimental::try` category when used. `try` and `catch` themselves were de-experimentalised in 5.40 and no longer warn. ## Contrast with `eval { ... }` / `$@` The older pattern is still supported, but `try`/`catch` fixes three long-standing pitfalls: | Pitfall | `eval` / `$@` | `try` / `catch` | |---|---|---| | `$@` clobbering between `eval` exit and the `if ($@)` check | real hazard, needs `local $@` dance | exception bound to a fresh lexical | | `return` inside the protected block | returns from the `eval`, not the sub | returns from the enclosing sub | | Distinguishing "no error" from "error was false" | `$@` can be falsey-but-set | `catch` only runs on a real throw | Use `try` for new code. Reach for `eval EXPR` only when you actually need string-`eval`'s runtime compilation. ## Examples Trap an exception and log it: ```perl use feature 'try'; try { my $x = call_a_function(); $x < 100 or die "too big: $x"; send_output($x); } catch ($e) { warn "unable to output a value: $e"; } print "finished\n"; ``` Use `try` as an expression inside [`do`](do) to pick a fallback: ```perl use feature 'try'; my $config = do { try { load_config($path) } catch ($e) { warn "using defaults: $e"; default_config() } }; ``` Release a resource unconditionally with `finally`: ```perl use feature 'try'; no warnings 'experimental::try'; # finally is still experimental my $lock = acquire_lock(); try { do_critical_work(); } catch ($e) { warn "critical work failed: $e"; } finally { release_lock($lock); } ``` Classify exceptions inside a single `catch` block: ```perl use feature 'try'; try { fetch_remote(); } catch ($e) { if (ref $e && $e->isa('Net::Timeout')) { retry_later(); } elsif (ref $e && $e->isa('Net::Auth')) { die $e; # rethrow auth failures } else { warn "unexpected: $e"; } } ``` `return` inside `try` returns from the enclosing sub — not just the block: ```perl use feature 'try'; sub first_valid { for my $path (@_) { try { return load($path); # exits first_valid on success } catch ($e) { warn "skip $path: $e"; } } return; # all paths failed } ``` ## Edge cases - **Feature guard required.** Without `use feature 'try'` (or a `use v5.34` or later bundle that enables it), `try` is a plain identifier and the construct is a syntax error. - **`catch` is mandatory.** `try { ... }` on its own is not legal — every `try` needs a `catch`. Use [`defer`](defer) or `finally` if you want cleanup without exception handling, paired with a trivial `catch ($e) { die $e }` rethrow if you also want to let the exception propagate. - **Rethrowing.** Inside `catch`, `die $e` rethrows. There is no implicit rethrow if you simply fall off the end of `catch`; doing so **swallows** the exception. Decide deliberately. - **`$@` is not cleared** by entering `try` and is not set by a caught exception. Do not read [`$@`](../perlvar) inside `catch` expecting the thrown value — read the lexical. - **`caller()` does not see `try`.** Like `while` or `foreach`, `try` is not a call frame. `caller` skips it, which is correct: since `return` propagates through `try`, `try` has no independent return semantics worth exposing to introspection. - **Loop controls pass through.** [`last`](last), [`next`](next), and [`redo`](redo) inside `try` or `catch` act on the enclosing loop, not on the `try` construct. A `finally` block will still run before the transfer completes. - **`finally` restrictions are enforced.** `return`, `goto`, and loop controls inside `finally` are errors. If you need conditional cleanup that may abort, do it in `catch` or outside the construct. - **No `try`-expression sugar beyond last-statement yield.** `try` is not a general expression; it can only produce a value when it is the final statement of a block that yields ([`do`](do), a sub). `my $x = try { ... } catch ($e) { ... };` is a syntax error. ## Differences from upstream Fully compatible with upstream Perl 5.42. - `try` and `catch` are non-experimental (as of 5.40) and emit no warnings. - `finally` is still experimental in 5.42 and emits `experimental::try` warnings when used; silence with `no warnings 'experimental::try'`. ## See also - [`catch`](catch) — the mandatory second block; receives the exception in a parenthesised lexical - [`finally`](finally) — optional third block for unconditional cleanup; still experimental in 5.42 - [`die`](die) — the throw side of the construct; any scalar (string, blessed ref, object) can be the thrown value - [`eval`](eval) — the older block-eval / `$@` pattern, still needed for string `eval`; prefer `try` for pure exception handling - [`defer`](defer) — unconditional cleanup without a surrounding `try`/`catch`; the semantic basis on which `finally` is defined - [`return`](return) — inside `try` returns from the enclosing sub, not from the block; inside `finally` it is an error