Aws-sdk-js: DynamoDB.DocumentClient should support empty string properties

Created on 10 Dec 2015  ·  174Comments  ·  Source: aws/aws-sdk-js

When the object contains a property with an empty string, it results in an exception instead of for example silently removing this property or replacing with a user-provided constant.

To be specific, the following example request:

var params = {
    TableName: 'my-test-table',
    Item: { Key:"foo", MyData: ""}
};

Results in the following error on DynamoDB:

[AWS dynamodb 400 0.588s 0 retries] putItem({ TableName: 'my-test-table',
  Item: { Key: { S: 'foo' }, MyData: { S: '' } } })

Which is returned from the DocumentClient as:

Unable to store request. Error was {
  "message": "One or more parameter values were invalid: An AttributeValue may not contain an empty string",
  "code": "ValidationException",
  "time": "2015-12-10T09:19:17.204Z",
  "statusCode": 400,
  "retryable": false,
  "retryDelay": 0
}
feature-request

Most helpful comment

I worked around this by just wiping out the empty keys from the object:

    var Item = { Key:"foo", MyData: "", Item: { Key:"foo", MyData: "", Item: { Key:"foo", MyData: ""}}};
    function removeEmptyStringElements(obj) {
      for (var prop in obj) {
        if (typeof obj[prop] === 'object') {// dive deeper in
          removeEmptyStringElements(obj[prop]);
        } else if(obj[prop] === '') {// delete elements that are empty strings
          delete obj[prop];
        }
      }
      return obj;
    }
    removeEmptyStringElements(Item);
/*
{
  "Key": "foo",
  "Item": {
    "Key": "foo",
    "Item": {
      "Key": "foo"
    }
  }
}
*/

All 174 comments

@thoean
What you're seeing is currently documented behavior:
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#putItem-property
String and Binary type attributes must have lengths greater than zero. Set type attributes cannot be empty. Requests with empty values will be rejected with a ValidationException exception.

This could be something we support in the future by having something like an ignoreEmptyStrings configuration option for the DocumentClient that was opt in.

Your proposal sounds great and would solve my use case.

Whether opt-in or standard behavior depends how much DocumentClient is a simplification over DynamoDB, not only in simplification of providing the necessary parameters, but also trying to do the right thing for the client. I think this case has arguments in both directions, so opt-in to maintain compatibility to its current version makes sense.

+1

+1

+1

+1

+1

+1

+1

+1

+1

I worked around this by just wiping out the empty keys from the object:

    var Item = { Key:"foo", MyData: "", Item: { Key:"foo", MyData: "", Item: { Key:"foo", MyData: ""}}};
    function removeEmptyStringElements(obj) {
      for (var prop in obj) {
        if (typeof obj[prop] === 'object') {// dive deeper in
          removeEmptyStringElements(obj[prop]);
        } else if(obj[prop] === '') {// delete elements that are empty strings
          delete obj[prop];
        }
      }
      return obj;
    }
    removeEmptyStringElements(Item);
/*
{
  "Key": "foo",
  "Item": {
    "Key": "foo",
    "Item": {
      "Key": "foo"
    }
  }
}
*/

+1

+1

Do we have support for empty strings in the latest version? If not, any timeline for this feature to be available? I have a specific case where I am persisting the payment response with hash. If I remove the keys with empty strings, the hash generation would fail later.

Hi @manikandants

Unfortunately, we can't share a timeline for this, but thanks for everyone who has given a +1 or voiced a concern about this feature request, as it helps us prioritize. I will look into this as soon as I can.

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

On Fri, Oct 28, 2016 at 2:29 PM, rtrompier [email protected] wrote:

+1


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/aws/aws-sdk-js/issues/833#issuecomment-256908063, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ACTfBJDHiiE36MoAsD9aENTITv7zoTfaks5q4eqMgaJpZM4GykZr
.

+1

+1

function cleanObj( o ) {
    if( o && o === o )
        if( typeof o === 'boolean' ) return o;
        else if( typeof o === 'number' ) return o;
        else if( typeof o === 'string' ) return o;
        else if( Array.isArray( o ) ) {
            let x = [], i = -1, l = o.length, r = 0;
            while( ++i < l ) if( o[ i ] ) x[ r++ ] = cleanObj( o[ i ] );
            return x;
        } else if( typeof o === 'object' ) {
            for( const k in o ) o[ k ] ? o[ k ] = cleanObj( o[ k ] ) : delete o[ k ];
            return o;
        } else
            return 'Argument Error - Unknown Item';
}

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1, and at least be more specific in error message.

+1

@LiuJoyceC could you disclose whether this is something that is actually being worked on or even discussed internally? I only ask because this bug seems to be almost a half-decade old. So is this something that actually could be fixed but hasn't, or is it a fundamental limitation of the DynamoDB internal structure?

Glad to see something is being done, but that's really just trading one problem for a new one.

+1

+1

@brandonmbanks Converting empty values to null is now an opt-in feature of the document client; you can pass a boolean convertEmptyValues option to the document client constructor to have it do so. I'll open a PR to improve the documentation of this feature.

+1

+1

+1

+1

+1

+1

+1

this is much needed, please...

@yipcma As noted above, this has been implemented as an opt-in feature. Set the convertEmptyValues constructor option to true when creating a document client.

@jeskew I think what people want is the ability to store and retrieve an empty string. All this provides is a way to convert empty strings to null which really isn't the same thing.

People want to be able to store JSON documents in DynamoDB but right now we only have two options: 1) store the full JSON as a string in a single column, or 2) use convertEmptyValues and accept that you will not be able to use 100% of the JSON spec without data loss.

Unfortunately, that isn't something that can be handled client-side without knowledge of the expected data schema.

If the SDK included a higher-level abstraction that knew which types certain fields were expected to be (like the AWS SDK for Java's DynamoDB Data Mapper or the Ruby Aws::Record), then the client could convert a null value to an empty string or empty buffer as appropriate. That's a reasonable feature request, but it's not something that could be built into the document client without introducing breaking changes.

+1 from me
+1 from Leanne

+1

+1

+1

+1

+1000

ive never seen a issue desired like this one. Any roadmap to implement the possibility to store an empty string in dynamodb? should everyone move to another database? 🙏🏼

@superandrew We've implemented opt-in, client-side support for this feature via the convertEmptyValues flag as discussed above.

in my opinion, this is more of a client side patch for something that needs to be done on the dynamodb side. And, more importantly, and as someone else said before me, null is no replacement for an empty string. So if more and more people keeps asking for a more complete fix, I wouldn't call this issue "closed". But, of course, still my opinion.

Just wanted to remind everyone to please keep the discussion constructive.

@superandrew I understand what you mean, but the SDK is a client-side library, and the DynamoDB team does not monitor the issue queue of any AWS SDK. For a server-side fix, I recommend that you reach out directly to the DynamoDB team via their AWS Developer Forum or via a support ticket.

@jeskew you can accelerate this type of request to AWS Team where plenty of people is facing issue with kind of problems! Though its almost 2 years, Developer finds a way on their(client) side as well!! LET IT GO!

@jeskew this bug is now more than half a decade old. No one seems to be getting satisfaction over there so they are voicing their concerns here. Perhaps AWS could open-source DynamoDB and put the code up on GitHub so we could create an issue there and/or make a PR which allows empty strings to be stored.

+1

+1

+1

Slight change to the code suggested by @bo01ean so that it tokenizes and detokenizes the empty string. It works for me but it's annoying that I need to do this to preserve the original JSON when using dynamodb.

const token = '~&*^AWSSTILLHASNOTFIXEDTHIS!!!~&*^';

const tokenizeEmptyStringElements = function (obj) {
  for (var prop in obj) {
    if (typeof obj[prop] === 'object') {// dive deeper in
      tokenizeEmptyStringElements(obj[prop]);
    } else if(obj[prop] === '') {
      // tokenize elements that are empty strings
      obj[prop] = token
    }
  }
  return obj;
}

const detokenizeEmptyStringElements = function (obj) {
  for (var prop in obj) {
    if (typeof obj[prop] === 'object') {// dive deeper in
      detokenizeEmptyStringElements(obj[prop]);
    } else if(obj[prop] === token) {
      // tokenize elements that are empty strings
      obj[prop] = ''
    }
  }
  return obj;
}

+1

+1

AWS Error Type: client, AWS Error Message: One or more parameter values were invalid: An AttributeValue may not contain an empty string

Validate empty string with " " SPACE

+1

+1

+1

+1

+1

+1

+8

+1

+1

+1

+1

+1

+1

+1

this is the single most requested thing I saw in my life.

Hi @superandrew,

You might want to check out the DynamoDB Data Mapper for JavaScript, which is now in developer preview. That project allows you to define your table schema up front so that empty strings can be saved as a sigil value compatible with DynamoDB's data model (null) and then deserialized back to an empty string when the item is loaded.

If you don't want to define a schema and don't mind transforming empty strings and buffers into null, you can also use the convertEmptyValues option on the Document client as discussed above.

thanks @jeskew as others have pointed out, this is not a problem of the js sdk but of dynamodb itself. I was just noticing how many people continue to request a dynamodb feature here because it's not possible to do it nowhere else.

+1

+1

+1

+1

lol

Trying to insert the data directly from a third party service which has almost 234 fields, some of them are empty. +1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+100000

+1

+1

+1

+9001

+1

const dynamodb = new AWS.DynamoDB.DocumentClient({
    convertEmptyValues: true,
});

convertEmptyValues changes them into null values not empty strings https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html

@chrisburkejr Empty string values will be rejected by DynamoDB; null is the only emptiness sigil that can be persisted in a DynamoDB table. If a particular field must always be a string, you could try using a schema-driven abstraction like the DynamoDB DataMapper, which can transparently handle empty strings.

This has been an issue for 5 years and has virtually no response on the DynamoDb forum, which is why you're getting hassled about it here. Maybe it's possible for you to raise this internally with the DynamoDb team so they can at the very least jump into the forum thread and address it with the users?

+1

+1

+1

convertEmptyValues: true

was enough to fix it for me.

+1

+1

+1

+1

@fptavares solution works just fine. It's documented here. Here is a quick example on usage:

module.exports.postback = (event, context, callback) => {
  const body = qs.parse(event['body']) || {}

  const params = {
    TableName: "conversions",
    Item: {
      "gclid": body.gclid,
      "leadid": body.leadid,
      "affid": body.affid,
      "campid": body.campid,
      "cid": body.cid,
      "tid": body.tid,
      "s1": body.s1,
      "s2": body.s2,
      "s3": body.s3,
      "s4": body.s4,
      "s5": body.s5,
      "price": body.price,
      "udid": body.udid,
    }
  }

  const dynamo = new AWS.DynamoDB.DocumentClient({
    convertEmptyValues: true
  })

  dynamo.put(params, (err, data) => {
     if (err) {
      Raven.captureException(err)
      return callback(err)
    }

    callback(null, {
      statusCode: 200,
      body: JSON.stringify({ "message": "success" })
    })
  })
}

As noted by @synergiclabs this solution will not store empty strings. Instead it will convert an empty string to null. If you require empty strings this solution is not for you.

@JamesTheHacker That is not a viable solution. The option convertEmptyValues converts a string into a NULL value. There are instances you really need EMPTY STRING and not a null data type.
In JavaScript, "" !== null;

@synergiclabs Of course, but in my instance and maybe for others, the solution is fine as I do not require empty strings to be stored. This was likely the decision amazon took too which is why they've provided no support.

+1

+1

+1

+1

+1

+1, we really need to persist empty string into database.

+1 ... read in some other issue that empty strings will be supported in DDB in 2018 .. any update when?

+1

+1

+1

+1

+1

+1

+1

can someone explain why setting an empty string would ever be considered invalid? this behavior makes no sense, the issue is closed, and it seems clearly incorrect despite being documented.

+1

+1

+1

+1

+1

+1

+1

+1

+1

@chrisradek , may I ask you to use the lock conversation feature to avoid having another million of +1s and notifying so many users? The DocumentClient solves this already with the convertEmptyValues: true option. And if the request is to store empty strings in dynamoDB, then the client library is the wrong repository to report this.

Thanks.

Just to be clear, convertEmptyValues does NOT solve the problem of dynamodb's inability to store empty strings. @thoean where is the correct place to report this issue if this isn't it?

@richard-gebbia I don't know the correct place. But it's not the client library as stated many times above. Best done via your account manager at AWS, or if your at a smaller contract probably just by filing a support ticket from your AWS account.

+1

This issue has been created on AWS forum for more than 6 years : https://forums.aws.amazon.com/thread.jspa?threadID=90137

Locking this thread. This is a service behavior that can not be addressed by the SDK. Locking to prevent continued spam.

Was this page helpful?
0 / 5 - 0 ratings