gildas-lormeau/SingleFile · error · Error
error.message + " (S3)"
Error message
error.message + " (S3)"
What it means
saveToS3 wraps any error from the S3 client upload (client.upload on a new S3(region, bucket, accessKey, secretKey, domain)) and rethrows it with an " (S3)" suffix plus the original as cause. This marks the failure as belonging to the S3 save destination.
Source
Thrown at src/core/bg/downloads.js:495
const client = new GitHub(githubToken, githubUser, githubRepository, githubBranch);
business.setCancelCallback(taskId, () => client.abort());
return await client.upload(filename, content, { filenameConflictAction, prompt });
}
} catch (error) {
throw new Error(error.message + " (GitHub)", { cause: error });
}
}
async function saveToS3(taskId, filename, blob, domain, region, bucket, accessKey, secretKey, { filenameConflictAction, prompt }) {
try {
const taskInfo = business.getTaskInfo(taskId);
if (!taskInfo || !taskInfo.cancelled) {
const client = new S3(region, bucket, accessKey, secretKey, domain);
business.setCancelCallback(taskId, () => client.abort());
return await client.upload(filename, blob, { filenameConflictAction, prompt });
}
} catch (error) {
throw new Error(error.message + " (S3)", { cause: error });
}
}
async function saveWithWebDAV(taskId, filename, content, url, username, password, { filenameConflictAction, prompt }) {
try {
const taskInfo = business.getTaskInfo(taskId);
if (!taskInfo || !taskInfo.cancelled) {
const client = new WebDAV(url, username, password);
business.setCancelCallback(taskId, () => client.abort());
return await client.upload(filename, content, { filenameConflictAction, prompt });
}
} catch (error) {
throw new Error(error.message + " (WebDAV)", { cause: error });
}
}
async function saveWithMCP(taskId, filename, content, serverUrl, authToken, { filenameConflictAction, prompt }) {
try {View on GitHub (pinned to 517fb7c5cf)
Solutions
- Check error.cause and verify accessKey/secretKey are correct and active
- Verify bucket name and region match (e.g. us-east-1) and the bucket exists
- Confirm the custom domain/endpoint URL is correct and reachable
- Ensure the credentials' policy allows s3:PutObject on the bucket
Example fix
// before
new S3('us-west-1', 'my-bucket', key, secret, domain); // bucket is in us-east-1
// after
new S3('us-east-1', 'my-bucket', key, secret, domain); Defensive patterns
Strategy: validation
Validate before calling
if (!region || !bucket || !accessKey || !secretKey) {
throw new Error('Missing S3 save configuration');
}
if (!/^s3[.-][a-z0-9-]+\.amazonaws\.com$/.test(domain || 's3.amazonaws.com') && !customEndpointOk) {
console.warn('Custom S3 domain, verify reachability');
} Type guard
function hasS3Config(o) {
return typeof o.region === 'string' && typeof o.bucket === 'string' &&
typeof o.accessKey === 'string' && o.accessKey.length > 0 &&
typeof o.secretKey === 'string' && o.secretKey.length > 0;
} Try / catch
try {
await saveToS3(taskId, filename, blob, s3Opts);
} catch (error) {
if (error.message.endsWith('(S3)')) {
const root = error.cause;
if (String(root).includes('403')) { /* fix credentials/policy */ }
} else { throw error; }
} Prevention
- Test S3 credentials with a HEAD bucket call during setup
- Keep bucket name and region consistent
- Prefer environment/secret storage for keys; rotate before expiry
- Check clock sync if signatures fail intermittently
When it happens
Trigger: Any rejection inside S3.upload(filename, blob, {filenameConflictAction, prompt}) called from downloadContent/downloadCompressedContent: bad credentials, wrong region/bucket, endpoint/domain unreachable, network error, or abort.
Common situations: Wrong accessKey/secretKey; bucket name typo or bucket in a different region; custom S3-compatible endpoint (domain) misconfigured (e.g. MinIO, Wasabi); clock skew causing signature errors; bucket policy denying PutObject.
Related errors
- error.message + " (GitHub)"
- error.message + " (WebDAV)"
- error.message + " (MCP)"
- error.message + " (RestFormApi)"
- response.statusText || "Error " + response.status
AI-assisted analysis of gildas-lormeau/SingleFile@517fb7c5cf (2026-09-01).
Data as JSON: /api/errors/5c4b500d5111993c.
Report an issue: GitHub.