The document path provided in the update expression is invalid for update

TL;DR — Estás escribiendo en una ruta anidada (SET parent.child = :v) pero parent no existe en el Item — o existe como string/number en vez de como map o list. DynamoDB NO crea automáticamente los maps intermedios. Crea el padre primero (SET #p = if_not_exists(#p, :emptyMap) en una actualización previa, o inicializa {} al crear el Item), y luego asigna el atributo anidado.

Qué significa

ValidationException: The document path provided in the update expression
is invalid for update

Una expresión de actualización puede direccionar rutas profundas (stats.daily.views, items[3].qty), pero cada paso de la ruta excepto el último debe existir ya en el Item con un tipo compatible. Si el Item no tiene atributo stats — o stats es un string — no hay dónde colgar daily, y la actualización se rechaza. La misma comprobación se ejecuta dentro de transacciones, donde aparece como un motivo de cancelación ValidationError.

Por qué ocurre

  • El map padre aún no existe — el Item se creó sin stats, y ahora SET stats.daily = :v no tiene ningún stats en el que descender.
  • El padre existe con el tipo equivocadostats es un string o un number, no un map (M), así que no tiene miembros que direccionar.
  • Indexar en una list inexistenteSET items[0].qty = :q cuando items no está en el Item o no es una list.
  • Un segmento de ruta con typoSET stat.daily = :v (falta la s) desciende en un atributo que no está ahí.
  • Items distintos tienen formas distintas — la actualización funciona en los Items que llevan el map y falla en los que no (habitual en diseños de tabla única con entidades mezcladas).

Cómo solucionarlo

  1. Inicializa los maps padre al crear el Item — escribe stats: {} (un M vacío) por adelantado, y las actualizaciones anidadas siempre tienen dónde aterrizar.

  2. O crea el padre bajo demanda, y luego asigna el hijo — dos actualizaciones. DynamoDB no te deja hacer ambas en una sola expresión (eso es un solapamiento de rutas):

    // update 1 — create the map only if it's missing
    UpdateExpression: 'SET #s = if_not_exists(#s, :empty)',
    ExpressionAttributeNames: {'#s': 'stats'},
    ExpressionAttributeValues: {':empty': {}}
    
    // update 2 — now the nested set is safe
    UpdateExpression: 'SET #s.#d = :v',
    ExpressionAttributeNames: {'#s': 'stats', '#d': 'daily'}

    Fíjate que if_not_exists(stats.daily, :v) no ayuda aquí: protege el valor, no el padre que falta.

  3. Reemplaza el map entero en su lugar cuando controlas toda su forma: SET #s = :wholeMap funciona exista o no stats.

  4. Verifica la forma real del Item — lee el Item y comprueba que el atributo padre existe y es un M/L antes de dar por válida la ruta.

La aplicación de escritorio DynoTable muestra de un vistazo la estructura anidada real de cada Item — puedes ver si stats es un map, un string o si falta por completo antes de escribir en él.

Errores relacionados

Referencias

Verificado por última vez el 2026-07-13 contra la documentación oficial de AWS enlazada arriba.

Trabaja con DynamoDB sin la Consola

DynoTable es un cliente de escritorio rápido para DynamoDB: explora tablas, ejecuta consultas estilo SQL y edita Items localmente.