Bug? INVALID_LOCALES when updating record via API


I am trying to update a record using the API, following the guidelines

My record has several languages available, only 'es-ES' mandatory.
I’m first creating the record in Spanish, and then trying to update it to add its English 'en' version.

When I perform a simple update operation, the function in returning following response:

    "data": [
            "id": "an id",
            "type": "api_error",
            "attributes": {
                "code": "INVALID_FIELD",
                "details": {
                    "field": "title",
                    "code": "INVALID_LOCALES",
                    "required_locales": [

Below is the code I’m using:

client.items.update(RECORD_ID, {
            title: { 'es-ES': 'Spanish title', en: 'English title' }

Am I doing something wrong? The rest of the operations work smooth (create record, upload image, etc.)


Edit: Please disregard this mistaken post. Correct answer coming in a sec.

Hi @fruizdiego, and welcome to the community!

Sorry about the issue you’re facing.

I’m trying to reproduce the error locally, but haven’t been able to yet.

Could you please verify for me that:

  • Your project only has the two locales, es-ES and en? No other ones?
  • Your model’s configuration for “All locales required?” is set to OFF
  • You’re using an appropriate API key with no locale restrictions?

Also, could you please share with me your project’s ID / dashboard URL so I can look around inside? You can DM me here (hover over my avatar by this post) or email me at r.tuan@datocms.com if you don’t want to make it public.

Thanks! As soon as I can get a little more detail, I’ll keep looking.

@fruizdiego, I apologize. Please disregard my previous post.

After some internal investigation, my colleague @m.finamor made me aware of an underlying issue (and a workaround!)

Despite what the error message says right now*, this is actually likely caused by having other localized fields in a model, but not providing data for them in the CMA update request.

If your model has localized fields title, description, extra_field, then:

client.items.update(RECORD_ID, {
            title: { 'es-ES': 'Spanish title', en: 'English title' }

Will unfortunately fail, with that cryptic error message. You actually just need to provide data (or nulls) for the other localized fields in that same request, like:

client.items.update(RECORD_ID, {
            title: { 'es-ES': 'Spanish title', en: 'English title' },
            description: { 'es-ES': 'Lorem ipsum', en: null},
            extra_field: { 'es-ES': null, en: null}

And that should go through. Sorry about that! (And thank you @m.finamor for clarifying that!)

* So if the issue is that all localized fields must be explicitly added to an update request (even just with nulls), why doesn’t the error message say that instead of suggesting there’s something wrong with title when there isn’t?

Good question. It’s a likely bug / oversight on our part. Sorry! I’ll flag it for the developers’ attention immediately :slight_smile:

In the meantime, please let us know if providing the additional fields in your request helps at all.

1 Like

Hi @roger, thanks for your quick response.

I have tried what you suggested and it actually works, thanks! It will do for now although it’s not the ideal situation. Here is why:

Our blog is multilanguage. Available locales are:


Not all the records are translated to all languages, but this approach means every post (~550) will be translated to every language and will be there (with null in every field), in the Admin panel.
For clarity and simplicity, the ideal situation for us would be to just have the translation of each post if it has actual content.

I have been checking the docs and you can’t remove a translation via API, can you?

Thanks! I mean it’s not the end of the world and the current workaround will do, but this little improvement will make it perfect.

You can actually leave out the locales you’re not working on. HOWEVER, SEE WARNING BELOW.

WARNING: Only follow these instructions if your other locales are EMPTY, or this will clear the other locales.

For example, if your project has en, es-ES, and it, and only es-ES has data right now, you can leave out the others. Whenever you update es-ES, you have to provide content or nulls for all the es-ES localized fields. But you don’t have to provide anything for en or it in those records, and they won’t show up in the admin panel.

If your other locales already have data, you have to fetch them first and then include their existing data back in your PUT request, even if you’re not touching those other locales. (I know, it’s silly.)

For example, if es-ES and it both have data already, you have to do something like this:

const existingRecord = await client.items.find(itemId)
/* existingRecord looks like this:

      "field1_localized": {
        "it": "italian title",
        "es-ES": "original spanish title"
      "field2_localized": {
        "it": "",
        "es-ES": "original spanish title for field 2"

let modifiedRecord = existingRecord
existingRecord['field1_localized']['es-ES'] = 'newer spanish title'
existingRecord['field2_localized']['es-ES'] = 'newer spanish title for field 2'


That will update the es-ES fields but leave it with whatever it was before, either filled out or not. en will remain empty in this example because it didn’t have data previously.

I have been checking the docs and you can’t remove a translation via API, can you?

Actually, you can, by just updating that record and leaving out a locale altogether. (Hence the warning). To be clear, if you update es-ES and it and leave out en, en will be removed from that record altogether. That’s why you have to make sure to fetch a record and pass along its existing data if en DOES have data already.

Thanks! I mean it’s not the end of the world and the current workaround will do, but this little improvement will make it perfect.

Sorry it’s all a bit confusing! Hopefully the above clears it up a little bit. I did flag this for developer review, though, so let’s see if they can make it any better.