# Audit Exception Safety

> Audit exception safety and failure atomicity across all throw sites

- Skill: `ben-manes/audit-exception-safety` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ben-manes/audit-exception-safety`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ben-manes/audit-exception-safety/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: ben-manes (https://skillmd.com/u/ben-manes)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/ben-manes/audit-exception-safety

---


Audit the cache for exception safety defects. For every code path where
exceptions can be thrown, determine whether the cache is left consistent.

Assume at least one exception safety bug exists. If your analysis yields
zero findings, re-examine catch-commit-rethrow paths — explain specifically
why no exception scenario leaves inconsistent state.

**Priority #1: catch-commit-rethrow in doComputeIfAbsent and remap.** This is
the most commonly misunderstood pattern and historically the most fragile.
Trace the EXACT sequence of committed mutations, notification delivery, and
exception propagation for every exception type.

User-provided code that can throw:
1. CacheLoader.load / loadAll / reload
2. Weigher.weigh
3. Expiry.expireAfterCreate / expireAfterUpdate / expireAfterRead
4. Mapping functions passed to compute, computeIfAbsent, merge
5. RemovalListener.onRemoval / EvictionListener

Runtime exceptions:
6. OutOfMemoryError during node/reference allocation
7. StackOverflowError from deep re-entrancy
8. RejectedExecutionException from executor

In the jcache adapter, also trace: CacheWriter.write/writeAll/delete/deleteAll
(the spec requires partial-failure bookkeeping), EntryProcessor.process,
ExpiryPolicy methods, and Copier/serialization failures in store-by-value mode.

For each throw site:

1. List every mutation already committed before the throw point.
2. Determine whether the catch block rolls back or commits.
3. Check for:
   - **Phantom entries**: Node in CHM but invisible to eviction/expiration
   - **Orphaned references**: WeakReference created but node rolled back
   - **Counter drift**: weightedSize out of sync with actual entries
   - **Lost notifications**: notifyEviction without notifyRemoval, or vice versa
   - **Leaked futures**: CompletableFuture never completed
   - **Stuck refresh**: refresh flag set but never cleared

4. For catch-commit-rethrow (doComputeIfAbsent, remap), verify:
   - Catches Throwable, not just RuntimeException
   - Committed state is fully consistent
   - Original exception is preserved

5. For OutOfMemoryError specifically:
   - Can AddTask/UpdateTask OOME orphan a CHM entry?
   - Can WeakKeyReference/WeakValueReference OOME leave half-constructed node?

For each defect: state the throw site, mutations committed, inconsistent
state, and a concrete triggering scenario.

