From 2be26ddbb78fa89ca9b9ee82ca6b30583ce8caae Mon Sep 17 00:00:00 2001 From: shadcn Date: Wed, 10 Jun 2026 12:12:54 +0400 Subject: [PATCH] fix(shadcn): surface network failure reason from fetch errors --- packages/shadcn/src/registry/proxy.ts | 47 +++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/packages/shadcn/src/registry/proxy.ts b/packages/shadcn/src/registry/proxy.ts index 43ec7a6e1..33abd1dbb 100644 --- a/packages/shadcn/src/registry/proxy.ts +++ b/packages/shadcn/src/registry/proxy.ts @@ -11,11 +11,44 @@ const proxyDispatcher = ? new EnvHttpProxyAgent() : undefined -export function fetchWithProxy(url: string | URL, init?: RequestInit) { - // The `dispatcher` option is supported by Node's fetch at runtime but - // missing from the ambient RequestInit type, hence the cast. - return fetch(url, { - ...init, - dispatcher: proxyDispatcher, - } as RequestInit) +export async function fetchWithProxy(url: string | URL, init?: RequestInit) { + try { + // The `dispatcher` option is supported by Node's fetch at runtime but + // missing from the ambient RequestInit type, hence the cast. + return await fetch(url, { + ...init, + dispatcher: proxyDispatcher, + } as RequestInit) + } catch (error) { + // Native fetch reports network failures as a generic "fetch failed" + // TypeError with the actual reason buried in `cause`. + if (error instanceof TypeError && error.cause) { + throw new Error( + `Request to ${url} failed, reason: ${getFailureReason(error.cause)}`, + { cause: error.cause } + ) + } + throw error + } +} + +function getFailureReason(cause: unknown): string { + // Connection failures surface as an AggregateError with an empty message + // and the per-address errors (e.g. ECONNREFUSED) in `errors`. + if (cause instanceof Error && "errors" in cause) { + const errors = (cause as Error & { errors: unknown }).errors + if (Array.isArray(errors) && errors.length) { + return getFailureReason(errors[0]) + } + } + + if (cause instanceof Error) { + return ( + cause.message || + (cause as NodeJS.ErrnoException).code || + "unknown error" + ) + } + + return String(cause) }