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

  1. Verify the bucket name exactly (no s3:// prefix, no trailing slash) in Joplin's sync settings.
  2. Confirm the bucket's region matches what Joplin is configured to use.
  3. Ensure the IAM user has s3:ListBucket and s3:GetObject/s3:PutObject on the bucket ARN.
  4. 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

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


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/3df18c105aa04b55. Report an issue: GitHub.