Skip to content

Commit 43777a5

Browse files
runningcodeclaude
andauthored
docs(agents): Forbid introducing new catch Throwable (#5944)
* docs(agents): Forbid introducing new catch Throwable Add an "Exception Handling" section to AGENTS.md telling agents to catch the narrowest exception type the guarded code can throw, and to never add a new catch (Throwable). The repo already has ~355 such catches in main sources; they are legacy and should not be read as a precedent. A broad catch swallows OutOfMemoryError, StackOverflowError, ThreadDeath and LinkageError, and hides bugs in our own code behind a log line. The "never crash the host app" requirement is what usually motivates these catches, so the section points at ExceptionUtils.rethrowIfFatal as the way to satisfy it, and calls out the two cases that need care: probing an optional compileOnly dependency via a LinkageError subclass, and not swallowing InterruptedException. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(agents): Drop the two related cases from Exception Handling The LinkageError and InterruptedException notes were detail the core rule does not need. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 32811a3 commit 43777a5

1 file changed

Lines changed: 27 additions & 0 deletions

File tree

‎AGENTS.md‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,33 @@ The repository is organized into multiple modules:
154154
- **Formatting**: Enforced via Spotless - always run `./gradlew spotlessApply` before committing
155155
- **API Compatibility**: Binary compatibility is enforced - run `./gradlew apiDump` after API changes
156156

157+
### Exception Handling
158+
159+
**Never introduce a new `catch (Throwable)`.** Catch the narrowest type the guarded code can
160+
actually throw. The repository still contains many pre-existing broad catches; they are legacy,
161+
not a precedent to follow.
162+
163+
A broad catch swallows `OutOfMemoryError`, `StackOverflowError`, `ThreadDeath` and `LinkageError` —
164+
conditions the JVM/ART cannot recover from and that leave the process in an undefined state — and
165+
it hides real bugs in our own code behind a log line.
166+
167+
"The SDK must never crash the host application" is not a reason to catch `Throwable`. That goal is
168+
served by `io.sentry.util.ExceptionUtils.rethrowIfFatal`, which lets the non-recoverable throwables
169+
through while leaving everything else for the caller to log or ignore:
170+
171+
```java
172+
try {
173+
doSomethingRisky();
174+
} catch (Throwable t) {
175+
ExceptionUtils.rethrowIfFatal(t);
176+
options.getLogger().log(SentryLevel.ERROR, "Failed to do something risky", t);
177+
}
178+
```
179+
180+
Apply that pattern only where a broad catch is genuinely unavoidable — an entry point that runs
181+
arbitrary user code or third-party callbacks. Everywhere else, name the exception types. Say in the
182+
PR description why the broad catch is necessary.
183+
157184
### Testing Requirements
158185
- Write comprehensive unit tests for new features
159186
- Android modules require both unit tests and instrumented tests where applicable

0 commit comments

Comments
 (0)