Skip to content

Commit 827995e

Browse files
JIWONKIMSclaude
andcommitted
fix(exception): Handle session invalidation gracefully
- Add special handling for "Session was invalidated" errors - Prevent cascading exceptions in GlobalExceptionHandler - Check response commit status before attempting to write - Reduce error log noise from expected session lifecycle events Fixes recursive exception handling when sessions expire during error responses. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2f79120 commit 827995e

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

src/main/kotlin/com/back/koreaTravelGuide/common/exception/GlobalExceptionHandler.kt

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.back.koreaTravelGuide.common.exception
22

33
import com.back.koreaTravelGuide.common.ApiResponse
44
import jakarta.servlet.http.HttpServletRequest
5+
import jakarta.servlet.http.HttpServletResponse
56
import org.slf4j.LoggerFactory
67
import org.springframework.http.HttpStatus
78
import org.springframework.http.ResponseEntity
@@ -43,7 +44,21 @@ class GlobalExceptionHandler {
4344
}
4445

4546
@ExceptionHandler(IllegalStateException::class)
46-
fun handleIllegalState(ex: IllegalStateException): ResponseEntity<ApiResponse<Void>> {
47+
fun handleIllegalState(
48+
ex: IllegalStateException,
49+
response: HttpServletResponse,
50+
): ResponseEntity<ApiResponse<Void>> {
51+
// Spring Session 무효화 예외는 별도 처리
52+
if (ex.message?.contains("Session was invalidated") == true) {
53+
logger.debug("Session invalidation during response (ignoring): {}", ex.message)
54+
// 응답이 이미 커밋되었을 수 있으므로 상태 코드만 설정
55+
if (!response.isCommitted) {
56+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse("세션이 만료되었습니다"))
57+
}
58+
// 이미 커밋된 경우 null 반환 (Spring이 처리)
59+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse("세션이 만료되었습니다"))
60+
}
61+
4762
logger.warn("부적절한 상태: {}", ex.message)
4863
return ResponseEntity.status(HttpStatus.CONFLICT).body(ApiResponse(ex.message ?: "요청을 처리할 수 없는 상태입니다"))
4964
}
@@ -52,7 +67,17 @@ class GlobalExceptionHandler {
5267
fun handleGenericException(
5368
ex: Exception,
5469
request: HttpServletRequest,
70+
response: HttpServletResponse,
5571
): ResponseEntity<ApiResponse<Void>> {
72+
// Spring Session 무효화 예외가 다른 예외 처리 중 발생한 경우
73+
if (ex is IllegalStateException && ex.message?.contains("Session was invalidated") == true) {
74+
logger.debug("Session invalidation during exception handling (ignoring): {}", ex.message)
75+
if (!response.isCommitted) {
76+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse("세션이 만료되었습니다"))
77+
}
78+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse("세션이 만료되었습니다"))
79+
}
80+
5681
// Static resource 예외는 무시 (favicon.ico, CSS, JS 등)
5782
if (ex is org.springframework.web.servlet.resource.NoResourceFoundException) {
5883
logger.debug("Static resource not found: {} at {}", ex.message, request.requestURI)

0 commit comments

Comments
 (0)