fix: console.error에 undefined를 넘기지 않는다 — 콘솔 계측 도구가 그 인자에서 터진다
`Cannot read properties of undefined (reading 'stack')`의 출처가 확인됐다. 우리 코드가 아니라
콘솔을 계측하는 개발 도구다 — VS Code 확장 Console Ninja가 소스의 `console.error`를
`oo_tx(...)`로 감싸는데, 그 안에서 인자 배열을 훑다가 `undefined`를 만나면 `.stack`을 읽고
터진다(사용자 콘솔 스택으로 확인: `communicationError (backend-fetch.ts:118)` → `console.eval`
→ `Array.find` → console-ninja).
그래서 `communicationError`가 값을 돌려주지 못하고 예외를 던졌고, `backendFetch`는
`{ok:false}` 대신 예외로 끝났다. 없는 엔드포인트(`POST /api/v1/mngr/quiz`)를 부르면 반드시
지나는 `예상치 못한 HTTP 상태` 분기가 `detail`로 `undefined`를 넘기고 있었다.
`detail`을 선택 인자로 바꾸고 없을 때는 아예 넘기지 않는다. 세 군데 호출부에서 `undefined`
인자를 걷어냈다. 계측 도구가 없어도 `console.error(msg, undefined)`는 로그에 의미 없는
`undefined`만 남기므로 어느 쪽이든 맞는 형태다.
Co-Authored-By: Claude Opus 5
@5c90ecc3c6afe29ea27b37c40676b89c996d296d
--- lib/http/backend-fetch.ts
+++ lib/http/backend-fetch.ts
... | ... | @@ -113,9 +113,23 @@ |
| 113 | 113 |
timeoutMs?: number; |
| 114 | 114 |
}; |
| 115 | 115 |
|
| 116 |
-function communicationError(reason: string, detail: unknown): BackendResult<never> {
|
|
| 117 |
- // 실패 상세는 서버 콘솔에만 남기고, 호출부·화면에는 일반화된 메시지만 전달한다. |
|
| 118 |
- console.error(`[backend-fetch] ${reason}`, detail);
|
|
| 116 |
+/** |
|
| 117 |
+ * 실패 상세는 서버 콘솔에만 남기고, 호출부·화면에는 일반화된 메시지만 전달한다. |
|
| 118 |
+ * |
|
| 119 |
+ * 이슈: `detail`이 `undefined`일 때 `console.error(msg, undefined)`로 부르면 안 된다. 콘솔을 |
|
| 120 |
+ * 계측하는 개발 도구(예: VS Code 확장 Console Ninja)가 인자를 훑다가 |
|
| 121 |
+ * `Cannot read properties of undefined (reading 'stack')`으로 터지고, 그러면 이 함수가 |
|
| 122 |
+ * 값을 돌려주지 못해 `backendFetch`가 결과 대신 예외를 던진다. 인자 자체를 넘기지 않는다. |
|
| 123 |
+ */ |
|
| 124 |
+function communicationError( |
|
| 125 |
+ reason: string, |
|
| 126 |
+ detail?: unknown |
|
| 127 |
+): BackendResult<never> {
|
|
| 128 |
+ if (detail === undefined) {
|
|
| 129 |
+ console.error(`[backend-fetch] ${reason}`);
|
|
| 130 |
+ } else {
|
|
| 131 |
+ console.error(`[backend-fetch] ${reason}`, detail);
|
|
| 132 |
+ } |
|
| 119 | 133 |
return {
|
| 120 | 134 |
ok: false, |
| 121 | 135 |
code: COMMUNICATION_ERROR_CODE, |
... | ... | @@ -201,8 +215,7 @@ |
| 201 | 215 |
} |
| 202 | 216 |
|
| 203 | 217 |
return communicationError( |
| 204 |
- `파일 응답의 예상치 못한 HTTP 상태: ${response.status}`,
|
|
| 205 |
- undefined |
|
| 218 |
+ `파일 응답의 예상치 못한 HTTP 상태: ${response.status}`
|
|
| 206 | 219 |
); |
| 207 | 220 |
} |
| 208 | 221 |
|
... | ... | @@ -285,7 +298,7 @@ |
| 285 | 298 |
}; |
| 286 | 299 |
} |
| 287 | 300 |
|
| 288 |
- return communicationError(`예상치 못한 HTTP 상태: ${response.status}`, undefined);
|
|
| 301 |
+ return communicationError(`예상치 못한 HTTP 상태: ${response.status}`);
|
|
| 289 | 302 |
} |
| 290 | 303 |
|
| 291 | 304 |
// 본문 없는 2xx를 허용한 호출은 먼저 글자를 읽어 비었는지 본다 — 비어 있으면 `response.json()`이 |
... | ... | @@ -380,8 +393,7 @@ |
| 380 | 393 |
}; |
| 381 | 394 |
} |
| 382 | 395 |
return communicationError( |
| 383 |
- `업로드 응답의 예상치 못한 HTTP 상태: ${response.status}`,
|
|
| 384 |
- undefined |
|
| 396 |
+ `업로드 응답의 예상치 못한 HTTP 상태: ${response.status}`
|
|
| 385 | 397 |
); |
| 386 | 398 |
} |
| 387 | 399 |
|
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?