s3: format errors with .Code

This commit is contained in:
Girish Ramakrishnan
2025-07-14 15:45:33 +02:00
parent 6b839c8cdc
commit 15ac81c1cd
2 changed files with 13 additions and 9 deletions

View File

@@ -44,6 +44,10 @@ function S3_NOT_FOUND(error) {
return error instanceof NoSuchKey || error instanceof NoSuchBucket;
}
function formatError(error) {
return `code: ${error.Code} message: ${error.message} HTTP: ${error.$metadata.httpStatusCode}`;
}
const RETRY_STRATEGY = new ConfiguredRetryStrategy(10 /* max attempts */, (/* attempt */) => 20000 /* constant backoff */);
function createS3Client(apiConfig, options) {
@@ -144,7 +148,7 @@ async function exists(apiConfig, backupFilePath) {
const [error, response] = await safe(s3.headObject(params));
if (error && S3_NOT_FOUND(error)) return false;
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error headObject ${backupFilePath}. Message: ${error.message} HTTP Code: ${error.$metadata.httpStatusCode}`);
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error headObject ${backupFilePath}. ${formatError(error)}`);
if (!response || typeof response.Metadata !== 'object') throw new BoxError(BoxError.EXTERNAL_ERROR, 'not a s3 endpoint');
return true;
@@ -156,7 +160,7 @@ async function exists(apiConfig, backupFilePath) {
};
const [error, listData] = await safe(s3.listObjectsV2(listParams));
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error listing objects ${backupFilePath}. Message: ${error.message} HTTP Code: ${error.$metadata.httpStatusCode}`);
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error listing objects ${backupFilePath}. ${formatError(error)}`);
return listData.Contents.length !== 0;
}
@@ -186,7 +190,7 @@ class S3MultipartDownloadStream extends Readable {
this.destroy(new BoxError(BoxError.NOT_FOUND, `Backup not found: ${this._path}`));
} else {
debug(`download: ${this._path} s3 stream error. %o`, error);
this.destroy(new BoxError(BoxError.EXTERNAL_ERROR, `Error multipartDownload ${this._path}. Message: ${error.message} HTTP Code: ${error.$metadata.httpStatusCode}`));
this.destroy(new BoxError(BoxError.EXTERNAL_ERROR, `Error multipartDownload ${this._path}. ${formatError(error)}`));
}
}
@@ -270,7 +274,7 @@ async function listDir(apiConfig, dir, batchSize, marker) {
if (marker) listParams.ContinuationToken = marker;
const [error, listData] = await safe(s3.listObjectsV2(listParams));
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error listing objects in ${dir}. Message: ${error.message} HTTP Code: ${error.$metadata.httpStatusCode}`);
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error listing objects in ${dir}. ${formatError(error)}`);
if (listData.Contents.length === 0) return { entries: [], marker: null }; // no more
const entries = listData.Contents.map(function (c) { return { fullPath: c.Key, size: c.Size }; });
return { entries, marker: !listData.IsTruncated ? null : listData.NextContinuationToken };
@@ -422,7 +426,7 @@ async function remove(apiConfig, filename) {
// deleteObjects does not return error if key is not found
const [error] = await safe(s3.deleteObjects(deleteParams));
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Unable to remove ${deleteParams.Key}. error: ${error.message}`);
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Unable to remove ${deleteParams.Key}. ${formatError(error)}`);
}
function chunk(array, size) {
@@ -530,7 +534,7 @@ async function testConfig(apiConfig) {
const s3 = createS3Client(apiConfig, {});
const [putError] = await safe(s3.putObject(putParams));
if (putError) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error put object cloudron-testfile. Message: ${putError.message} HTTP Code: ${putError.$metadata.httpStatusCode}`);
if (putError) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error put object cloudron-testfile. ${formatError(putError)}`);
const listParams = {
Bucket: apiConfig.bucket,
@@ -539,7 +543,7 @@ async function testConfig(apiConfig) {
};
const [listError] = await safe(s3.listObjectsV2(listParams));
if (listError) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error listing objects. Message: ${listError.message} HTTP Code: ${listError.$metadata.httpStatusCode}`);
if (listError) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error listing objects. ${formatError(listError)}`);
const delParams = {
Bucket: apiConfig.bucket,
@@ -547,7 +551,7 @@ async function testConfig(apiConfig) {
};
const [delError] = await safe(s3.deleteObject(delParams));
if (delError) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error del object cloudron-testfile. Message: ${delError.message} HTTP Code: ${delError.$metadata.httpStatusCode}`);
if (delError) throw new BoxError(BoxError.EXTERNAL_ERROR, `Error del object cloudron-testfile. ${formatError(delError)}`);
}
function removePrivateFields(apiConfig) {