(error: unknown)
| 156 | }) |
| 157 | |
| 158 | export function logError(error: unknown): void { |
| 159 | const err = toError(error) |
| 160 | if (feature('HARD_FAIL') && isHardFailMode()) { |
| 161 | // biome-ignore lint/suspicious/noConsole:: intentional crash output |
| 162 | console.error('[HARD FAIL] logError called with:', err.stack || err.message) |
| 163 | // eslint-disable-next-line custom-rules/no-process-exit |
| 164 | process.exit(1) |
| 165 | } |
| 166 | try { |
| 167 | // Check if error reporting should be disabled |
| 168 | if ( |
| 169 | // Cloud providers (Bedrock/Vertex/Foundry) always disable features |
| 170 | isEnvTruthy(process.env.CLAUDE_CODE_USE_BEDROCK) || |
| 171 | isEnvTruthy(process.env.CLAUDE_CODE_USE_VERTEX) || |
| 172 | isEnvTruthy(process.env.CLAUDE_CODE_USE_FOUNDRY) || |
| 173 | process.env.DISABLE_ERROR_REPORTING || |
| 174 | isEssentialTrafficOnly() |
| 175 | ) { |
| 176 | return |
| 177 | } |
| 178 | |
| 179 | const errorStr = err.stack || err.message |
| 180 | |
| 181 | const errorInfo = { |
| 182 | error: errorStr, |
| 183 | timestamp: new Date().toISOString(), |
| 184 | } |
| 185 | |
| 186 | // Always add to in-memory log (no dependencies needed) |
| 187 | addToInMemoryErrorLog(errorInfo) |
| 188 | |
| 189 | // If sink not attached, queue the event |
| 190 | if (errorLogSink === null) { |
| 191 | errorQueue.push({ type: 'error', error: err }) |
| 192 | return |
| 193 | } |
| 194 | |
| 195 | errorLogSink.logError(err) |
| 196 | } catch { |
| 197 | // pass |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | export function getInMemoryErrors(): { error: string; timestamp: string }[] { |
| 202 | return [...inMemoryErrorLog] |
no test coverage detected