ExpressionAttributeNames contains invalid key: Syntax error

TL;DR — O problema é a chave de placeholder no lado esquerdo do seu map ExpressionAttributeNames, não o atributo para o qual ela aponta. Um placeholder precisa ser # seguido de letras, dígitos ou underscores simples (#name, #p0). Se você colocar o nome real do atributo — com seus pontos, hífens, sinais de + ou espaços — dentro do próprio placeholder, o DynamoDB rejeita o map. Mantenha os placeholders sem graça; ponha o nome real bagunçado no lado direito.

O que significa

ValidationException: ExpressionAttributeNames contains invalid key:
Syntax error; key: "#my.attribute"

ExpressionAttributeNames mapeia um token de placeholder (usado dentro da sua expressão) para um nome de atributo real. O DynamoDB valida a sintaxe do placeholder antes de tocar nos seus dados: ele precisa começar com # e conter apenas caracteres que são válidos dentro de um token de expressão. Caracteres especiais que significam algo na gramática de expressão — . (separador de caminho), -, +, espaços — tornam o próprio placeholder impossível de fazer parse, e a requisição inteira é rejeitada com este ValidationException.

Por que acontece

  • O nome real do atributo foi copiado para o placeholder — por exemplo, {"#stats.daily": "stats.daily"}. O ponto na chave é um erro de sintaxe, independentemente do que ela mapeia.
  • Caracteres especiais no placeholder — hífens (#user-id), sinais de +, ou espaços. Apenas alfanuméricos e underscores são seguros após o #.
  • Um # ausente — chaves em ExpressionAttributeNames precisam começar com #; {"name": "name"} é inválido.
  • Uma biblioteca gerando placeholders automaticamente a partir de nomes de atributo que contêm pontos ou caracteres especiais, passando o caractere direto.

Como corrigir

  1. Use placeholders simples e mapeie cada um para o nome real:

    {
      ExpressionAttributeNames: {'#p0': 'user-id', '#p1': 'stats'},
      KeyConditionExpression: '#p0 = :uid'
    }
  2. Para caminhos aninhados, aliase cada segmento separadamente — um placeholder por elemento de caminho, unidos por um ponto literal na expressão:

    // read stats.daily where the item has a top-level "stats" map
    {
      ProjectionExpression: '#s.#d',
      ExpressionAttributeNames: {'#s': 'stats', '#d': 'daily'}
    }

    Note o outro lado: se o nome real do atributo contém um ponto literal (um atributo chamado "stats.daily", não um caminho aninhado), um único placeholder para o nome inteiro é exatamente o que você quer — {'#sd': 'stats.daily'} — para que o ponto seja tratado como parte do nome, não um separador de caminho.

  3. Confira o que seu wrapper gera — se um ODM/helper constrói o map por você, faça log da requisição final e inspecione as chaves de placeholder que ele produziu.

Trabalhando com atributos cujos nomes são cheios de pontos e traços? O app desktop DynoTable constrói suas consultas com nomes devidamente aliasados automaticamente, seja qual for o nome do atributo.

Erros relacionados

Referências

Verificado pela última vez em 2026-07-13 contra a documentação oficial da AWS vinculada acima.

Trabalhe com o DynamoDB sem o Console

O DynoTable é um cliente desktop rápido para o DynamoDB — navegue pelas tabelas, execute consultas no estilo SQL e edite itens localmente.