aws-sdk-js-v3
aws-sdk-js-v3 copied to clipboard
Misleading error message - Cannot read property 'byteLength' of undefined
Describe the bug
The exception Cannot read property 'byteLength' of undefined is thrown by a client instance in many cases, but, as pointed out in https://github.com/aws/aws-sdk-js-v3/issues/2411#issuecomment-864127937, the problem might be, that keys in the credentials object are spelled in PascalCase, instead of camelCase.
I just had the same problem, and this was indeed what caused it. What makes it worse is the fact, that in the SDK Reference, lower-case properties marked as readonly, so you would never think to dig in that direction.
Your environment
SDK version number
@aws-sdk/client-s3@v3, @aws-sdk/lib-storage@v3
Is the issue in the browser/Node.js/ReactNative?
Browser
Thanks for bringing this up, a better error message should be populated. Will take it to the team to decide the priority for this.
I am seeing the same error, despite having all keys in camelCase
import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";
const awsConfiguration = {
region: "us-east-1",
credentials: {
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
},
};
const dynamodbClient = new DynamoDBClient(awsConfiguration);
I'm having this exact same issue with an IAMClient and errors with the following code snippet:
iam = new iamc.IAMClient({
region: region,
credentials: {
accessKeyId: client_params.AccessKeyId,
secretAccessKey: client_params.SecretAccessKey,
sessionToken: client_params.SessionToken
}
})
Same issue, regardless of if PascalCase or camelCase notation is used.
const credentials = {
SessionToken: process.env.AWS_SESSION_TOKEN
}
const client = new CloudFormationClient({
credentials,
region: 'us-east-2',
});
+1 here :(
I've tested this using full admin credentials and also temp credentials scoped to 1 single bucket, either way I always get the same error:
/application/node_modules/@aws-sdk/util-buffer-from/dist-cjs/index.js:6
const fromArrayBuffer = (input, offset = 0, length = input.byteLength - offset) => {
^
TypeError: Cannot read properties of undefined (reading 'byteLength')
at fromArrayBuffer (/application/node_modules/@aws-sdk/util-buffer-from/dist-cjs/index.js:6:60)
at castSourceData (/application/node_modules/@aws-sdk/hash-node/dist-cjs/index.js:29:51)
at Hash.update (/application/node_modules/@aws-sdk/hash-node/dist-cjs/index.js:12:26)
at hmac (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/credentialDerivation.js:36:10)
at getSigningKey (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/credentialDerivation.js:11:29)
at SignatureV4.getSigningKey (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/SignatureV4.js:153:57)
at SignatureV4.signRequest (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/SignatureV4.js:98:73)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async /application/node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:13:18
at async StandardRetryStrategy.retry (/application/node_modules/@aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46) {
'$metadata': { attempts: 1, totalRetryDelay: 0 }
}
this is my code:
import { S3Client, S3ClientConfig, ListObjectsCommand, ListObjectsCommandInput } from '@aws-sdk/client-s3'
...
private s3Client: S3Client;
constructor(accessKey: string, secretAccessKey: string) {
this.config = {
region: "ap-southeast-2",
credentials: {
accessKeyId: accessKey,
secretAccessKey: secretAccessKey
}
}
this.s3Client = new S3Client(this.config);
}
public async getS3Objects(bucketName: string) {
const params: ListObjectsCommandInput = {
Bucket: 'my-bucket'
};
const command = new ListObjectsCommand(params);
return await this.s3Client.send(command);
}
My bucket has the following settings:
- Name: my-bucket
- Region: Asia Pacific (Sydney) ap-southeast-2
- Access: Bucket and objects not public. // Tried also making all the objects public, and got same result :/
- Versioning: Disabled
- Encryption: Amazon S3-managed keys (SSE-S3)
Not sure if this is useful, but this is the config object I get when logging on the console after I created the S3Client instance:
this.s3Client {
apiVersion: '2006-03-01',
disableHostPrefix: false,
logger: {},
regionInfoProvider: [AsyncFunction: defaultRegionInfoProvider],
serviceId: 'S3',
signerConstructor: [class SignatureV4MultiRegion],
signingEscapePath: false,
urlParser: [Function: parseUrl],
useArnRegion: [AsyncFunction (anonymous)],
region: [AsyncFunction: region],
credentials: [Function (anonymous)],
runtime: 'node',
defaultsMode: [AsyncFunction (anonymous)],
base64Decoder: [Function: fromBase64],
base64Encoder: [Function: toBase64],
bodyLengthChecker: [Function: calculateBodyLength],
credentialDefaultProvider: [Function (anonymous)],
defaultUserAgentProvider: [AsyncFunction (anonymous)],
eventStreamSerdeProvider: [Function: eventStreamSerdeProvider],
getAwsChunkedEncodingStream: [Function: getAwsChunkedEncodingStream],
maxAttempts: [AsyncFunction (anonymous)],
md5: [Function: bound Hash],
requestHandler: NodeHttpHandler {
metadata: { handlerProtocol: 'http/1.1' },
configProvider: Promise { <pending> }
},
retryMode: [AsyncFunction (anonymous)],
sha1: [Function: bound Hash],
sha256: [Function: bound Hash],
streamCollector: [Function: streamCollector],
streamHasher: [Function: readableStreamHasher],
useDualstackEndpoint: [AsyncFunction (anonymous)],
useFipsEndpoint: [AsyncFunction: useFipsEndpoint],
utf8Decoder: [Function: fromUtf8],
utf8Encoder: [Function: toUtf8],
tls: true,
endpoint: [Function (anonymous)],
isCustomEndpoint: false,
retryStrategy: [AsyncFunction: retryStrategy],
systemClockOffset: 0,
signer: [Function: signer],
bucketEndpoint: false,
forcePathStyle: false,
useAccelerateEndpoint: false,
disableMultiregionAccessPoints: [Function (anonymous)],
customUserAgent: undefined,
eventStreamMarshaller: EventStreamMarshaller {
universalMarshaller: EventStreamMarshaller {
eventStreamCodec: [EventStreamCodec],
utfEncoder: [Function: toUtf8]
}
}
}
the command:
command: ListObjectsCommand {
middlewareStack: {
add: [Function: add],
addRelativeTo: [Function: addRelativeTo],
clone: [Function: clone],
use: [Function: use],
remove: [Function: remove],
removeByTag: [Function: removeByTag],
concat: [Function: concat],
applyToStack: [Function: cloneTo],
resolve: [Function: resolve]
},
input: { Bucket: 'my-bucket' }
}
+1 here :(
I've tested this using full admin credentials and also temp credentials scoped to 1 single bucket, either way I always get the same error:
/application/node_modules/@aws-sdk/util-buffer-from/dist-cjs/index.js:6 const fromArrayBuffer = (input, offset = 0, length = input.byteLength - offset) => { ^ TypeError: Cannot read properties of undefined (reading 'byteLength') at fromArrayBuffer (/application/node_modules/@aws-sdk/util-buffer-from/dist-cjs/index.js:6:60) at castSourceData (/application/node_modules/@aws-sdk/hash-node/dist-cjs/index.js:29:51) at Hash.update (/application/node_modules/@aws-sdk/hash-node/dist-cjs/index.js:12:26) at hmac (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/credentialDerivation.js:36:10) at getSigningKey (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/credentialDerivation.js:11:29) at SignatureV4.getSigningKey (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/SignatureV4.js:153:57) at SignatureV4.signRequest (/application/node_modules/@aws-sdk/signature-v4/dist-cjs/SignatureV4.js:98:73) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /application/node_modules/@aws-sdk/middleware-signing/dist-cjs/middleware.js:13:18 at async StandardRetryStrategy.retry (/application/node_modules/@aws-sdk/middleware-retry/dist-cjs/StandardRetryStrategy.js:51:46) { '$metadata': { attempts: 1, totalRetryDelay: 0 } }this is my code:
import { S3Client, S3ClientConfig, ListObjectsCommand, ListObjectsCommandInput } from '@aws-sdk/client-s3' ... private s3Client: S3Client; constructor(accessKey: string, secretAccessKey: string) { this.config = { region: "ap-southeast-2", credentials: { accessKeyId: accessKey, secretAccessKey: secretAccessKey } } this.s3Client = new S3Client(this.config); } public async getS3Objects(bucketName: string) { const params: ListObjectsCommandInput = { Bucket: 'my-bucket' }; const command = new ListObjectsCommand(params); return await this.s3Client.send(command); }My bucket has the following settings:
- Name: my-bucket
- Region: Asia Pacific (Sydney) ap-southeast-2
- Access: Bucket and objects not public. // Tried also making all the objects public, and got same result :/
- Versioning: Disabled
- Encryption: Amazon S3-managed keys (SSE-S3)
Not sure if this is useful, but this is the config object I get when logging on the console after I created the S3Client instance:
this.s3Client { apiVersion: '2006-03-01', disableHostPrefix: false, logger: {}, regionInfoProvider: [AsyncFunction: defaultRegionInfoProvider], serviceId: 'S3', signerConstructor: [class SignatureV4MultiRegion], signingEscapePath: false, urlParser: [Function: parseUrl], useArnRegion: [AsyncFunction (anonymous)], region: [AsyncFunction: region], credentials: [Function (anonymous)], runtime: 'node', defaultsMode: [AsyncFunction (anonymous)], base64Decoder: [Function: fromBase64], base64Encoder: [Function: toBase64], bodyLengthChecker: [Function: calculateBodyLength], credentialDefaultProvider: [Function (anonymous)], defaultUserAgentProvider: [AsyncFunction (anonymous)], eventStreamSerdeProvider: [Function: eventStreamSerdeProvider], getAwsChunkedEncodingStream: [Function: getAwsChunkedEncodingStream], maxAttempts: [AsyncFunction (anonymous)], md5: [Function: bound Hash], requestHandler: NodeHttpHandler { metadata: { handlerProtocol: 'http/1.1' }, configProvider: Promise { <pending> } }, retryMode: [AsyncFunction (anonymous)], sha1: [Function: bound Hash], sha256: [Function: bound Hash], streamCollector: [Function: streamCollector], streamHasher: [Function: readableStreamHasher], useDualstackEndpoint: [AsyncFunction (anonymous)], useFipsEndpoint: [AsyncFunction: useFipsEndpoint], utf8Decoder: [Function: fromUtf8], utf8Encoder: [Function: toUtf8], tls: true, endpoint: [Function (anonymous)], isCustomEndpoint: false, retryStrategy: [AsyncFunction: retryStrategy], systemClockOffset: 0, signer: [Function: signer], bucketEndpoint: false, forcePathStyle: false, useAccelerateEndpoint: false, disableMultiregionAccessPoints: [Function (anonymous)], customUserAgent: undefined, eventStreamMarshaller: EventStreamMarshaller { universalMarshaller: EventStreamMarshaller { eventStreamCodec: [EventStreamCodec], utfEncoder: [Function: toUtf8] } } }the
command:command: ListObjectsCommand { middlewareStack: { add: [Function: add], addRelativeTo: [Function: addRelativeTo], clone: [Function: clone], use: [Function: use], remove: [Function: remove], removeByTag: [Function: removeByTag], concat: [Function: concat], applyToStack: [Function: cloneTo], resolve: [Function: resolve] }, input: { Bucket: 'my-bucket' } }
I actually made it work, by adding the sessionToken as part of the config:
constructor(accessKey: string, secretAccessKey: string, sessionToken: string) {
this.config = {
region: "ap-southeast-2",
credentials: {
accessKeyId: accessKey,
secretAccessKey: secretAccessKey,
sessionToken: sessionToken
}
}
this.s3Client = new S3Client(this.config);
}
Note: The credentials + sessionToken that I'm passing here are temp credentials I've got from calling the command: GetCredentialsForIdentityCommand
Hope this helps someone else :)
Removing the needs-review because we know it requires a better error message. But it's not blocking customer from making request to AWS services. We will implement a fix soon.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.