ExpressionAttributeNames contains invalid key: Syntax error
TL;DR — Le problème vient de la clé de placeholder située à gauche de ta map ExpressionAttributeNames, pas de l'attribut vers lequel elle pointe. Un placeholder doit être un # suivi de simples lettres, chiffres ou underscores (#name, #p0). Si tu mets le vrai nom d'attribut — avec ses points, tirets, signes + ou espaces — dans le placeholder lui-même, DynamoDB rejette la map. Garde des placeholders banals ; mets le vrai nom compliqué du côté droit.
Ce que ça signifie
ValidationException: ExpressionAttributeNames contains invalid key:
Syntax error; key: "#my.attribute"ExpressionAttributeNames associe un jeton de placeholder (utilisé dans ton expression) à un vrai nom d'attribut. DynamoDB valide la syntaxe du placeholder avant de toucher à tes données : il doit commencer par # et ne contenir que des caractères valides dans un jeton d'expression. Les caractères spéciaux qui ont un sens dans la grammaire d'expression — . (séparateur de chemin), -, +, espaces — rendent le placeholder lui-même impossible à analyser, et toute la requête est rejetée avec cette ValidationException.
Pourquoi ça arrive
- Le vrai nom d'attribut a été copié dans le placeholder — par ex.
{"#stats.daily": "stats.daily"}. Le point dans la clé est une erreur de syntaxe, quel que soit ce vers quoi il pointe. - Des caractères spéciaux dans le placeholder — tirets (
#user-id), signes+ou espaces. Seuls les caractères alphanumériques et les underscores sont sûrs après le#. - Un
#manquant — les clés deExpressionAttributeNamesdoivent commencer par#;{"name": "name"}est invalide. - Une bibliothèque qui auto-génère des placeholders à partir de noms d'attributs contenant des points ou des caractères spéciaux, laissant passer le caractère tel quel.
Comment la corriger
Utilise des placeholders simples et associe chacun au vrai nom :
{ ExpressionAttributeNames: {'#p0': 'user-id', '#p1': 'stats'}, KeyConditionExpression: '#p0 = :uid' }Pour les chemins imbriqués, aliase chaque segment séparément — un placeholder par élément de chemin, joints par un point littéral dans l'expression :
// read stats.daily where the item has a top-level "stats" map { ProjectionExpression: '#s.#d', ExpressionAttributeNames: {'#s': 'stats', '#d': 'daily'} }Note le revers : si le nom réel de l'attribut contient un point littéral (un seul attribut nommé
"stats.daily", pas un chemin imbriqué), un seul placeholder pour le nom entier est exactement ce qu'il te faut —{'#sd': 'stats.daily'}— pour que le point soit traité comme faisant partie du nom, et non comme un séparateur de chemin.Vérifie ce que génère ton wrapper — si un ODM/helper construit la map à ta place, journalise la requête finale et inspecte les clés de placeholder qu'il a produites.
Tu travailles avec des attributs dont les noms sont pleins de points et de tirets ? L'application de bureau DynoTable construit ses requêtes avec des noms correctement aliasés automatiquement, quel que soit le nom de l'attribut.
Erreurs liées
- Attribute name is a reserved keyword — l'autre grande raison d'utiliser
ExpressionAttributeNames. - Value provided in ExpressionAttributeNames unused in expressions
- Value provided in ExpressionAttributeValues unused
- Apprends : Expression names & values
Références
- Expression attribute names (aliases) in DynamoDB — Amazon DynamoDB Developer Guide
- Query — Amazon DynamoDB API Reference
- Reserved words in DynamoDB — Amazon DynamoDB Developer Guide
Dernière vérification le 2026-07-13 par rapport à la documentation officielle AWS liée ci-dessus.