From e494015e9a9f02427230fc8c8e6b1834aae60474 Mon Sep 17 00:00:00 2001 From: salmanrajz Date: Thu, 2 Apr 2026 12:12:24 +0400 Subject: [PATCH] fix: wrap streaming reader in try/finally to release lock and prevent resource leaks Partially addresses #112. The streaming reader in openaiStreamToAnthropic had no error handling - if an error occurred during streaming, the reader lock was never released. Wrapped the while loop in try/finally to ensure reader.releaseLock() is always called. --- src/services/api/openaiShim.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/services/api/openaiShim.ts b/src/services/api/openaiShim.ts index 017af0d1..c3b8566b 100644 --- a/src/services/api/openaiShim.ts +++ b/src/services/api/openaiShim.ts @@ -412,15 +412,16 @@ async function* openaiStreamToAnthropic( const decoder = new TextDecoder() let buffer = '' - while (true) { - const { done, value } = await reader.read() - if (done) break + try { + while (true) { + const { done, value } = await reader.read() + if (done) break - buffer += decoder.decode(value, { stream: true }) - const lines = buffer.split('\n') - buffer = lines.pop() ?? '' + buffer += decoder.decode(value, { stream: true }) + const lines = buffer.split('\n') + buffer = lines.pop() ?? '' - for (const line of lines) { + for (const line of lines) { const trimmed = line.trim() if (!trimmed || trimmed === 'data: [DONE]') continue if (!trimmed.startsWith('data: ')) continue @@ -566,6 +567,9 @@ async function* openaiStreamToAnthropic( hasEmittedFinalUsage = true } } + } + } finally { + reader.releaseLock() } yield { type: 'message_stop' }