From d699036b7606d20e9ee8d1b7a1f8b88afbb856d8 Mon Sep 17 00:00:00 2001 From: kdletters Date: Tue, 30 Jun 2026 16:06:41 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E4=B8=8A=E4=BC=A0=E9=94=99=E8=AF=AF=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为 OSS 上传失败补充备份对象路径上下文 输出错误 cause 链和网络字段,便于定位 fetch failed (cherry picked from commit 48ee0eb75dd84e2db95f828b256f233e6618f5d9) --- scripts/database-backup-to-oss.mjs | 69 +++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/scripts/database-backup-to-oss.mjs b/scripts/database-backup-to-oss.mjs index 4c5587b3d..79f408ad1 100644 --- a/scripts/database-backup-to-oss.mjs +++ b/scripts/database-backup-to-oss.mjs @@ -396,16 +396,21 @@ async function uploadArchive({archivePath, bucket, endpoint, objectKey, accessKe }); console.log(`[database-backup] 上传 OSS: oss://${bucket}/${objectKey}`); - const response = await fetch(targetUrl, { - method: 'PUT', - headers: { - ...headers, - authorization, - 'content-length': String(fileStat.size), - }, - body: createReadStream(archivePath), - duplex: 'half', - }); + let response; + try { + response = await fetch(targetUrl, { + method: 'PUT', + headers: { + ...headers, + authorization, + 'content-length': String(fileStat.size), + }, + body: createReadStream(archivePath), + duplex: 'half', + }); + } catch (error) { + throw new Error(`OSS 上传请求失败: oss://${bucket}/${objectKey}`, {cause: error}); + } const responseText = await response.text(); if (!response.ok) { @@ -584,7 +589,49 @@ async function main() { } } +function formatErrorDetails(error) { + if (!error || typeof error !== 'object') { + return ''; + } + return ['code', 'errno', 'syscall', 'hostname', 'host', 'port', 'address'] + .map((field) => { + const value = error[field]; + return value === undefined || value === null || value === '' ? '' : `${field}=${String(value)}`; + }) + .filter(Boolean) + .join(' '); +} + +function describeError(error) { + const lines = []; + let current = error; + for (let depth = 0; current && depth < 5; depth += 1) { + const label = depth === 0 ? 'error' : `cause[${depth}]`; + if (!(current instanceof Error)) { + lines.push(`${label}: ${String(current)}`); + break; + } + + lines.push(`${label}: ${current.name}: ${current.message}`); + const details = formatErrorDetails(current); + if (details) { + lines.push(`${label} details: ${details}`); + } + if (current instanceof AggregateError) { + current.errors.slice(0, 3).forEach((item, index) => { + const itemText = item instanceof Error ? `${item.name}: ${item.message}` : String(item); + const itemDetails = formatErrorDetails(item); + lines.push(`${label}.errors[${index}]: ${itemText}${itemDetails ? ` (${itemDetails})` : ''}`); + }); + } + current = current.cause; + } + return lines; +} + main().catch((error) => { - console.error(`[database-backup] ${error instanceof Error ? error.message : String(error)}`); + for (const line of describeError(error)) { + console.error(`[database-backup] ${line}`); + } process.exit(1); });