Skip to content

Commit c9ca1e8

Browse files
vraj00222claude
andcommitted
fix(sdk): broaden connection-error patterns for custom provider wrapper
Bun's fetch surfaces ECONNREFUSED as code='ConnectionRefused' with message "Unable to connect. Is the computer able to access the url?". Neither matched the original error-wrap regex. Now check both the raw message and the error.code property across Bun/Node patterns. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 4c6aebf commit c9ca1e8

1 file changed

Lines changed: 22 additions & 1 deletion

File tree

sdk/src/impl/llm.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,23 @@ function buildCustomProviderError(args: {
143143
baseUrl: string
144144
model: string
145145
rawMessage: string
146+
rawCode?: string
146147
}): string {
147148
const lower = args.rawMessage.toLowerCase()
149+
const codeLower = (args.rawCode ?? '').toLowerCase()
148150
const isConnectionError =
149151
lower.includes('econnrefused') ||
152+
lower.includes('connectionrefused') ||
153+
lower.includes('connection refused') ||
154+
lower.includes('unable to connect') ||
150155
lower.includes('fetch failed') ||
151156
lower.includes('etimedout') ||
152157
lower.includes('enotfound') ||
153-
lower.includes('socket hang up')
158+
lower.includes('socket hang up') ||
159+
codeLower === 'connectionrefused' ||
160+
codeLower === 'econnrefused' ||
161+
codeLower === 'enotfound' ||
162+
codeLower === 'etimedout'
154163
const isModelNotFound =
155164
lower.includes('model not found') ||
156165
lower.includes('does not exist') ||
@@ -545,11 +554,16 @@ export async function* promptAiSdkStream(
545554
yield* response.fullStream
546555
} catch (e) {
547556
const rawMessage = e instanceof Error ? e.message : String(e)
557+
const rawCode =
558+
e && typeof e === 'object' && 'code' in e
559+
? String((e as { code?: unknown }).code ?? '')
560+
: undefined
548561
throw new Error(
549562
buildCustomProviderError({
550563
baseUrl: resolvedBaseUrl,
551564
model: params.model,
552565
rawMessage,
566+
rawCode,
553567
}),
554568
)
555569
}
@@ -704,11 +718,18 @@ export async function* promptAiSdkStream(
704718
// For custom-provider failures, rewrap with a friendly, actionable message
705719
// before throwing so users see "is Ollama running?" not raw "fetch failed".
706720
if (isCustomProvider && resolvedBaseUrl) {
721+
const rawCode =
722+
chunkValue.error &&
723+
typeof chunkValue.error === 'object' &&
724+
'code' in chunkValue.error
725+
? String((chunkValue.error as { code?: unknown }).code ?? '')
726+
: undefined
707727
throw new Error(
708728
buildCustomProviderError({
709729
baseUrl: resolvedBaseUrl,
710730
model: params.model,
711731
rawMessage: errorMessage,
732+
rawCode,
712733
}),
713734
)
714735
}

0 commit comments

Comments
 (0)