ExpressionAttributeNames contains invalid key: Syntax error
TL;DR — El problema es la clave del marcador de posición en el lado izquierdo de tu mapa ExpressionAttributeNames, no el atributo al que apunta. Un marcador de posición debe ser # seguido de letras, dígitos o guiones bajos simples (#name, #p0). Si pones el nombre real del atributo — con sus puntos, guiones, signos + o espacios — dentro del propio marcador, DynamoDB rechaza el mapa. Mantén los marcadores de posición aburridos; pon el nombre real desordenado en el lado derecho.
Qué significa
ValidationException: ExpressionAttributeNames contains invalid key:
Syntax error; key: "#my.attribute"ExpressionAttributeNames mapea un token de marcador de posición (usado dentro de tu expresión) a un nombre de atributo real. DynamoDB valida la sintaxis del marcador de posición antes de tocar tus datos: debe empezar por # y contener solo caracteres válidos dentro de un token de expresión. Los caracteres especiales que significan algo en la gramática de la expresión — . (separador de ruta), -, +, espacios — hacen que el propio marcador de posición no sea analizable, y toda la solicitud se rechaza con esta ValidationException.
Por qué ocurre
- El nombre real del atributo se copió en el marcador de posición — p. ej.
{"#stats.daily": "stats.daily"}. El punto en la clave es un error de sintaxis, independientemente de lo que mapee. - Caracteres especiales en el marcador de posición — guiones (
#user-id), signos+o espacios. Solo los alfanuméricos y los guiones bajos son seguros después del#. - Un
#ausente — las claves deExpressionAttributeNamesdeben empezar por#;{"name": "name"}es inválido. - Una librería que autogenera marcadores de posición a partir de nombres de atributo que contienen puntos o caracteres especiales, pasando el carácter directamente.
Cómo solucionarlo
Usa marcadores de posición simples y mapea cada uno al nombre real:
{ ExpressionAttributeNames: {'#p0': 'user-id', '#p1': 'stats'}, KeyConditionExpression: '#p0 = :uid' }Para rutas anidadas, alias cada segmento por separado — un marcador de posición por elemento de ruta, unidos por un punto literal en la expresión:
// read stats.daily where the item has a top-level "stats" map { ProjectionExpression: '#s.#d', ExpressionAttributeNames: {'#s': 'stats', '#d': 'daily'} }Fíjate en el reverso: si el nombre real del atributo contiene un punto literal (un atributo llamado
"stats.daily", no una ruta anidada), un único marcador de posición para el nombre completo es exactamente lo que quieres —{'#sd': 'stats.daily'}— para que el punto se trate como parte del nombre, no como un separador de ruta.Comprueba qué genera tu wrapper — si un ODM/helper construye el mapa por ti, registra la solicitud final e inspecciona las claves de marcador de posición que produjo.
¿Trabajas con atributos cuyos nombres están llenos de puntos y guiones? La app de escritorio DynoTable construye sus consultas con nombres correctamente aliasados de forma automática, se llame como se llame el atributo.
Errores relacionados
- Attribute name is a reserved keyword — la otra gran razón para usar
ExpressionAttributeNames. - Value provided in ExpressionAttributeNames unused in expressions
- Value provided in ExpressionAttributeValues unused
- Aprende: Expression names & values
Referencias
- Expression attribute names (aliases) in DynamoDB — Amazon DynamoDB Developer Guide
- Query — Amazon DynamoDB API Reference
- Reserved words in DynamoDB — Amazon DynamoDB Developer Guide
Verificado por última vez el 2026-07-13 contra la documentación oficial de AWS enlazada arriba.