markvgti
markvgti

Reputation: 4619

Getting 'str.indexOf is not a function' error when trying to S3.getSignedUrl()

While trying to get a signed URL for a getObject I am getting the following error from the aws-sdk library:

<proj-dir>\node_modules\aws-sdk\lib\util.js:983
      return str && str.indexOf('arn:') === 0 && str.split(':').length >= 6;
                        ^

TypeError: str.indexOf is not a function
    at Object.validateARN [as validate] (<proj-dir>\node_modules\aws-sdk\lib\util.js:983:25)
    at features.constructor.hasBucketInParams [as isAccessPointApplicable] (<proj-dir>\node_modules\aws-sdk\lib\services\s3.js:180:2
3)
    at features.constructor.setupRequestListeners (<proj-dir>\node_modules\aws-sdk\lib\services\s3.js:126:14)
    at features.constructor.addAllRequestListeners (<proj-dir>\node_modules\aws-sdk\lib\service.js:276:10)
    at features.constructor.makeRequest (<proj-dir>\node_modules\aws-sdk\lib\service.js:203:10)
    at features.constructor.getSignedUrl (<proj-dir>\node_modules\aws-sdk\lib\services\s3.js:1026:24)
    at Object.<anonymous> (<proj-dir>\s3-test.js:101:8)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Module.load (internal/modules/cjs/loader.js:811:32)

Other S3 calls (like listBuckets) are working fine. Here's my test file:

const S3 = require('./utils/s3Util');
const C = require('./utils/constants');
const _ = require('lodash');

// other code...

S3.svc.getSignedUrl('getObject', { Bucket: C.S3_BUCKET, Key: 'TestFrequencyCount.java', Expires: 60 }).promise()
    .then(retVal => {
        console.log("Return value:", retVal);
    }).catch(err => {
        console.log("Error::", err);
    });

The s3Util.js file:

const C = require('./constants');
const AWS = require('aws-sdk');
const keys = require("../config/aws-config.json");

// AWS.config.update(keys);

const s3 = new AWS.S3({...keys, apiVersion: C.S3_API_VER, signatureVersion: 'v4' });

module.exports = Object.freeze({
    svc: s3,
});

I was using aws-sdk version 2.610.0, then updated that to 2.621.0, but the problem remains.

Even tried by changing the way I was loading the AWS account credentials (will use an IAM user once I have things figured out) based on a combination of this note from AWS SDK documentation:

Note: You must ensure that you have static or previously resolved credentials if you call this method synchronously (with no callback), otherwise it may not properly sign the request. If you cannot guarantee this (you are using an asynchronous credential provider, i.e., EC2 IAM roles), you should always call this method with an asynchronous callback.

and the solution given at Node.js and aws credentials error - json (which suggested not using AWS.config.loadFromPath(path) but instead loading the parameters directly through AWS.config.update(...)), but to no avail.

In deseparation I tried the callback version as well, but as expected it gave the same result:

S3.svc.getSignedUrl('getObject', { Bucket: C.S3_BUCKET, Key: 'TestFrequencyCount.java', Expires: 60 }, (err, retVal) => {
    if (err) {
        console.log("Error::", err);
    } else {
        console.log("Return value:", retVal);
    }
});

Upvotes: 0

Views: 1997

Answers (2)

markvgti
markvgti

Reputation: 4619

The error was with the definition of C.S3_BUCKET: it should have been used instead as: C.S3_BUCKET[process.env.NODE_ENV].

Upvotes: 2

IOOIIIO
IOOIIIO

Reputation: 599

str variable is probably an object, not a string or array, so indexOf method cannot be applied to it. Use console.log(str) to confirm this.

Upvotes: 1

Related Questions