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 emExpressionAttributeNamesprecisam 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
Use placeholders simples e mapeie cada um para o nome real:
{ ExpressionAttributeNames: {'#p0': 'user-id', '#p1': 'stats'}, KeyConditionExpression: '#p0 = :uid' }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.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
- Attribute name is a reserved keyword — o outro grande motivo para usar
ExpressionAttributeNames. - Value provided in ExpressionAttributeNames unused in expressions
- Value provided in ExpressionAttributeValues unused
- Aprenda: Expression names & values
Referências
- Expression attribute names (aliases) in DynamoDB — Amazon DynamoDB Developer Guide
- Query — Amazon DynamoDB API Reference
- Reserved words in DynamoDB — Amazon DynamoDB Developer Guide
Verificado pela última vez em 2026-07-13 contra a documentação oficial da AWS vinculada acima.