laurent22/joplin · error · Error
AWS S3 bucket not found: ${SyncTargetAmazonS3.s3BucketName()
Error message
AWS S3 bucket not found: ${SyncTargetAmazonS3.s3BucketName()} What it means
Thrown by SyncTargetAmazonS3.checkConfig after a HeadBucketCommand against the configured bucket. If the AWS SDK resolves the promise but with a falsy result, the bucket is treated as not found / not accessible. The bucket name comes from SyncTargetAmazonS3.s3BucketName(). Other AWS errors propagate via the catch block and surface as errorMessage instead.
Source
Thrown at packages/lib/SyncTargetAmazonS3.js:127
errorMessage: '',
};
try {
const fileApi = await SyncTargetAmazonS3.newFileApi_(SyncTargetAmazonS3.id(), options);
fileApi.requestRepeatCount_ = 0;
const headBucketReq = new Promise((resolve, reject) => {
fileApi.driver().api().send(
new HeadBucketCommand({
Bucket: options.path(),
}), (error, response) => {
if (error) reject(error);
else resolve(response);
});
});
const result = await headBucketReq;
if (!result) throw new Error(`AWS S3 bucket not found: ${SyncTargetAmazonS3.s3BucketName()}`);
output.ok = true;
} catch (error) {
if (error.message) {
output.errorMessage = error.message;
}
if (error.code) {
output.errorMessage += ` (Code ${error.code})`;
}
}
return output;
}
async initFileApi() {
const appDir = '';
const fileApi = new FileApi(appDir, new FileApiDriverAmazonS3(this.api(), SyncTargetAmazonS3.s3BucketName()));
fileApi.setSyncTargetId(SyncTargetAmazonS3.id());
View on GitHub (pinned to 2654b33620)
Solutions
- Verify the bucket name exactly (no s3:// prefix, no trailing slash) in Joplin's sync settings.
- Confirm the bucket's region matches what Joplin is configured to use.
- Ensure the IAM user has s3:ListBucket and s3:GetObject/s3:PutObject on the bucket ARN.
- Test with `aws s3 ls s3://<bucket>` using the same credentials to isolate Joplin vs AWS.
Example fix
# before aws s3 ls s3://my-buket # NoSuchBucket # after (fix typo in Joplin sync settings) bucket: my-bucket aws s3 ls s3://my-bucket # OK
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check bucket accessibility with the same AWS creds before starting sync.
const { HeadBucketCommand } = require('@aws-sdk/client-s3');
const ok = await s3Client.send(new HeadBucketCommand({ Bucket: bucketName }));
if (!ok) throw new Error(`Bucket not reachable: ${bucketName}`); Type guard
const isNonEmptyBucketName = (s) => typeof s === 'string' && s.length > 0 && !s.includes('://') && !s.endsWith('/'); Try / catch
try { await SyncTargetAmazonS3.checkConfig(options); }
catch (e) { if (/S3 bucket not found/.test(e.message)) { /* verify name/region/IAM */ } else throw e; } Prevention
- Verify the bucket name with `aws s3 ls` using the same credentials before configuring Joplin.
- Confirm the IAM policy grants s3:HeadBucket, s3:ListBucket, s3:GetObject, s3:PutObject on the bucket ARN.
When it happens
Trigger: checkConfig() runs HeadBucketCommand({ Bucket: options.path() }) — the promise resolves to a falsy value (no error thrown, but no bucket metadata either). Typically indicates the bucket name is wrong, the region is wrong, or credentials lack s3:ListBucket on that bucket.
Common situations: Typo in the S3 sync path; bucket exists in a different region; IAM credentials have no HeadBucket permission; bucket name with a trailing slash; using a virtual-host vs path-style URL mismatch.
Related errors
- Could not access data on server "${options.path()}"
- WebDAV directory not found: ${options.path()}
- rejectedByTarget
- uploadBlob: ${method} ${url}: ${error.toString()}
- lockError
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/3df18c105aa04b55.
Report an issue: GitHub.