laurent22/joplin · error · JoplinError
rejectedByTarget
rejectedByTarget
Error message
Do not have proper permissions to Bucket
What it means
A JoplinError (code 'rejectedByTarget') thrown in the S3 driver's read/get path when the server returns an AccessDenied error parsed from the XML response body. It signals the configured AWS credentials lack read (GetObject/list) permission on the target bucket. Upstream sync code treats 'rejectedByTarget' specially — the item is skipped and logged rather than marked 'cannotSyncItem'.
Source
Thrown at packages/lib/file-api-driver-amazon-s3.js:281
// This means that the error was on the Desktop client side and we need to handle that.
// On Mobile it won't match because FetchError is a node-fetch feature.
// https://github.com/node-fetch/node-fetch/blob/main/docs/ERROR-HANDLING.md
if (error.name === 'FetchError') { throw error.message; }
let parsedOutput = '';
// If error.output is not xml the last else case should
// actually let us see the output of error.
if (error.output) {
parsedOutput = parser.parse(error.output);
if (this.hasErrorCode_(parsedOutput.Error, 'AuthorizationHeaderMalformed')) {
throw error.output;
}
if (this.hasErrorCode_(parsedOutput.Error, 'NoSuchKey')) {
return null;
} else if (this.hasErrorCode_(parsedOutput.Error, 'AccessDenied')) {
throw new JoplinError('Do not have proper permissions to Bucket', 'rejectedByTarget');
}
} else {
if (error.output) {
throw error.output;
} else {
throw error;
}
}
}
}
// Don't need to make directories, S3 is key based storage.
async mkdir() {
return true;
}
async put(path, content, options = null) {
const remotePath = this.makePath_(path);View on GitHub (pinned to 2654b33620)
Solutions
- Update the IAM policy for the configured credentials to grant s3:GetObject (and s3:ListBucket if listing fails) on the bucket.
- If using SSE-KMS, ensure kms:Decrypt permission on the encrypting key.
- Verify the bucket policy explicitly allows the principal and doesn't have an explicit Deny.
- Confirm the bucket name and region in the sync config are correct.
Defensive patterns
Strategy: try-catch
Validate before calling
// Before configuring S3 sync, validate credentials have read access
// (best done via a preflight HEAD/GetObject on a known key)
try {
await s3.send(new HeadObjectCommand({ Bucket, Key: '.joplin' }));
} catch (e) {
// credentials lack read permission; fix IAM before syncing
} Type guard
import JoplinError from './JoplinError';
function isRejectedByTarget(e: unknown): e is JoplinError {
return e instanceof JoplinError && (e as any).code === 'rejectedByTarget';
} Try / catch
try {
await driver.get(path);
} catch (error) {
if (isRejectedByTarget(error)) {
// skip this item; log a warning; do not mark as cannotSyncItem
logger.warn('Item rejected by target', path, error.message);
return;
}
throw error;
} Prevention
- Grant s3:GetObject (and s3:ListBucket) to the IAM principal used for sync.
- If using SSE-KMS, also grant kms:Decrypt on the bucket's key.
- Treat 'rejectedByTarget' as a per-item skip, not a fatal sync error.
When it happens
Trigger: The S3 driver performs a GET-like operation (read of an object); AWS returns an XML error containing <Code>AccessDenied</Code>; the driver parses it and throws this. The AWS credentials in the sync config have permission to reach the bucket but not to read objects.
Common situations: IAM user/role with write but not read permissions on the bucket; bucket policy denies the principal; KMS key missing decrypt permission for SSE-encrypted objects; wrong bucket region/endpoint causing auth mismatch; credentials rotated to a lesser role.
Related errors
- AWS S3 bucket not found: ${SyncTargetAmazonS3.s3BucketName()
- s3UploadFileFrom: file does not exist
- rejectedByTarget
- isReadOnly
- No item with ID ${itemId}
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/bd559187cb114880.
Report an issue: GitHub.