ExpressionAttributeNames contém chave inválida: erro de sintaxe

TL;DR — O problema é a chave de espaço reservado no lado esquerdo do seu mapa ExpressionAttributeNames, não o atributo para o qual ela aponta. Um espaço reservado deve ser # seguido por letras simples, dígitos ou sublinhados (#name, #p0). Se você colocar o nome real do atributo — com seus pontos, hífens, sinais + ou espaços — no próprio espaço reservado, o DynamoDB rejeitará o mapa. Mantenha os espaços reservados enfadonhos; coloque o nome verdadeiro bagunçado no lado direito.

O que significa

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

# what the engine actually returns, reproduced against DynamoDB Local:
ValidationException: 1 validation error detected: ExpressionAttributeNames contains invalid key: Syntax error; key: "#my.attribute"

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

Por que isso acontece

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

Como corrigir

  1. Use espaços reservados simples e mapeie cada um para o nome real:

    {
      ExpressionAttributeNames: {'#p0': 'user-id', '#p1': 'stats'},
      KeyConditionExpression: '#p0 = :uid'
    }
  2. Para caminhos aninhados, apelide cada segmento separadamente — um espaço reservado por elemento do 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'}
    }

    Observe 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 espaço reservado para o nome inteiro é exatamente o que você deseja - {'#sd': 'stats.daily'} - então o ponto é tratado como parte do nome, não como um separador de caminho.

  3. Verifique o que seu wrapper gera — se um ODM/helper construir o mapa para você, registre a solicitação final e inspecione as chaves de espaço reservado que ele produziu.

  4. Nunca coloque separadores de caminho em chaves de espaço reservado. Os pontos pertencem à string de expressão entre tokens #segment, e não dentro de uma única chave #.

Verifique no DynoTable

O DynoTable cria consultas com espaços reservados simples com prefixo # - nomes de atributos com pontos, traços ou palavras reservadas são alias corretamente no lado direito do mapa. Abra uma tabela com ⌘K, adicione filtros e copie o ExpressionAttributeNames gerado.

Verifique os nomes dos atributos no verificador de palavras reservadas ao escrever aliases à mão. Alternar perfis com ⌘P; consulte Conectar ao AWS e Instalar.

Fontes

Erros relacionados

Referências

Última verificação em 13/07/2026 em relação à documentação oficial do AWS vinculada acima.

Trabalhe com o DynamoDB sem o Console

Um cliente desktop rápido para DynamoDB que roda o SQL de verdade que o DynamoDB não consegue — JOINs, GROUP BY, agregações — com edição visual e um agente de IA com suas próprias chaves do Bedrock.

Teste grátis de 30 dias, sem cartão de crédito — depois o plano Grátis sem limite de tempo.