skip to content

Tell me about TransactionTimedOutException: what type is it, when is it thrown, and how does it differ from a database lock timeout or a JDBC query timeout?

level: seniorimportance: should knowfreq 22%

answer

  1. Extends TransactionException -> RuntimeException (unchecked)
  2. Thrown by ResourceHolderSupport.checkTransactionTimeout
  3. Sets rollbackOnly then throws at a boundary
  4. Query timeout -> QueryTimeoutException (different)
  5. Lock wait -> PessimisticLockingFailureException (different)

basics

~20 s

TransactionTimedOutException is Spring's unchecked exception (a TransactionException) thrown when a transaction's timeout deadline has passed and Spring tries to use the resource again. It forces a rollback. It's distinct from a DB lock timeout or a JDBC query timeout, which are database-level errors surfaced as SQLExceptions.

solid answer

~40 s

org.springframework.transaction.TransactionTimedOutException extends TransactionException, which is a RuntimeException — so it's unchecked and, being a Spring exception, triggers rollback under the default rules. It's thrown by Spring's own code: ResourceHolderSupport.checkTransactionTimeout, invoked from getTimeToLiveInMillis/Seconds, throws it when the recorded deadline is in the past, marking the holder rollback-only. Contrast with two lower-level things Spring may leverage but which are different exceptions: a JDBC query timeout (from Statement.setQueryTimeout being exceeded) surfaces as a SQLException, typically translated by Spring to QueryTimeoutException; and a database lock/statement timeout (e.g., Postgres lock_timeout, MySQL innodb_lock_wait_timeout) also comes back as a driver SQLException, translated to a PessimisticLockingFailureException or similar. So TransactionTimedOutException specifically means 'Spring's transaction deadline elapsed and was detected at a boundary,' not 'the database killed my query.'

code

java · 9 lines
java
// TransactionTimedOutException is unchecked and forces rollback.
try {
    reportService.generateHeavyReport(); // @Transactional(timeout = 5)
} catch (org.springframework.transaction.TransactionTimedOutException ex) {
    // The tx is already rollback-only. Don't 'recover' and continue the same tx.
    log.warn("Report tx exceeded its 5s budget: {}", ex.getMessage());
    // Distinct from QueryTimeoutException (DB cancelled one query) and
    // PessimisticLockingFailureException (DB lock wait timed out).
}

go deeper

for a junior

Know it's unchecked and means the transaction ran past its timeout and rolled back.

for a middle

Place it in the TransactionException hierarchy and know it's thrown by Spring, not the driver.

for a senior

Distinguish it from QueryTimeoutException and PessimisticLockingFailureException and explain rollback-only marking.

for a principal

Use the distinction to design layered timeouts (Spring tx timeout + DB statement/lock timeouts) and correct error handling that doesn't try to continue a rollback-only tx.

## Type and hierarchy `org.springframework.transaction.TransactionTimedOutException` extends `TransactionException`, which extends `NestedRuntimeException` -> `RuntimeException`. Therefore it is **unchecked** (you don't declare it) and, under Spring's default rollback rules (`RuntimeException`/`Error` -> rollback), it causes the transaction to roll back. ## Where and when it's thrown It's thrown by **Spring itself**, not the driver. `ResourceHolderSupport` records an absolute `deadline` when the timeout is set. Its `checkTransactionTimeout(boolean deadlineReached)` method does: ```java if (deadlineReached) { setRollbackOnly(); throw new TransactionTimedOutException("Transaction timed out: deadline was " + this.deadline); } ``` This fires from `getTimeToLiveInMillis()/getTimeToLiveInSeconds()` — i.e., whenever Spring computes the remaining budget (to apply a query timeout or otherwise use the resource) and finds the deadline already passed. So it's detected at a **statement/resource boundary**, and it sets `rollbackOnly` before throwing. ## How it differs from neighbours 1. **JDBC query timeout exceeded** — `Statement.setQueryTimeout(n)` was set (possibly by Spring's own timeout machinery) and the DB cancelled the running query. The driver throws a `SQLException` (often with a timeout SQL state). Spring's `SQLExceptionTranslator` typically maps it to `org.springframework.dao.QueryTimeoutException` (a `TransientDataAccessException`). This is 'the DB stopped one query,' whereas `TransactionTimedOutException` is 'Spring's overall transaction budget elapsed.' 2. **Database lock wait timeout** — e.g., Postgres `lock_timeout`, MySQL `innodb_lock_wait_timeout`. The row you want is locked by another transaction; after the DB's own wait limit, the driver throws a `SQLException`, which Spring translates to `PessimisticLockingFailureException` / `CannotAcquireLockException`. Again, driver-originated, not Spring's transaction timeout. 3. **`javax.persistence.QueryTimeoutException` / `LockTimeoutException`** — JPA-level equivalents when using an `EntityManager`; Spring's JPA exception translation maps these into the `org.springframework.dao` hierarchy. ## Practical consequences - Because it's a Spring `RuntimeException`, catching it and swallowing it does **not** un-mark the transaction — the transaction is already rollback-only; the commit will fail with `UnexpectedRollbackException` if you try to proceed. - When you see `TransactionTimedOutException` in logs, the fix is usually to widen the `timeout`, speed up the work, move slow non-DB work out of the transaction, or split into `REQUIRES_NEW` units — not to add try/catch. - For robust systems, layer the Spring timeout with DB-side `statement_timeout`/`lock_timeout` so a hung query is killed even if `setQueryTimeout` isn't honored by the driver. ## Message you'll see Typical log: `org.springframework.transaction.TransactionTimedOutException: Transaction timed out: deadline was <timestamp>`.

  • Is TransactionTimedOutException checked or unchecked, and does it roll back?
    Unchecked — it extends TransactionException / RuntimeException. Under Spring's default rules a RuntimeException rolls the transaction back, and the exception itself marks the holder rollback-only before being thrown.
  • If the database cancels a single query that exceeded setQueryTimeout, do you get a TransactionTimedOutException?
    Not directly — that's a driver SQLException, which Spring translates to QueryTimeoutException. TransactionTimedOutException comes from Spring's own deadline check at a resource boundary.

saying these in an interview costs you the question

  • Saying it's a checked exception you must declare
  • Confusing it with SQL/JDBC query-timeout SQLExceptions or lock-timeout exceptions
  • Believing catching it lets you keep using the same transaction

context