🐛 Bug Report: Transaction upsert ignores rowId and creates a new row
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 82/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- php, postgresql
- Área
- backend-api-design, databases
Línea de trabajo
Empieza por src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php, especialmente handleUpsertOperation() alrededor de las líneas 678–682, y traza cómo el documentId de la operación llega a la llamada de upsert. Usa los pasos de reproducción para comprobar que al confirmar un upsert se actualiza el ID de fila especificado, y que se usa un ID de fila no existente para la fila creada.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
👟 Reproduction steps
- Table with columns
status(string) andn(integer); create rowup1withstatus = "open",n = 0. POST /v1/tablesdb/transactions→ transactionT.- Stage an upsert the way the API documents operations (row ID in
rowId, values indata):{"operations": [{"action": "upsert", "databaseId": "db", "tableId": "t", "rowId": "up1", "data": {"status": "done", "n": 1}}]} PATCH /v1/tablesdb/transactions/Twithcommit: true→200.- Read row
up1, and list rows withstatus = "done".
👍 Expected behavior
Row up1 now has status = "done", n = 1 (or, for a non-existing rowId, a row with that ID is created).
👎 Actual Behavior
- Row
up1is unchanged (status = "open",n = 0). - Instead a new row with a generated ID (e.g.
6ac5371741b960276721) withstatus = "done",n = 1was created. - For a non-existing
rowIdthe same happens: no row with that ID, but a new row with a random ID. - Staging returns
201, commit returns200– there is no error.
Adding "$id": "up1" inside data makes it work, so only the rowId field of the operation is ignored. In a sync that uses transactional upserts this silently produces duplicates and never updates the intended rows (30 of 30 attempts in our test).
Cause: handleUpsertOperation() builds the document from data only and never sets the operation's documentId (Transactions/Update.php L678–L682):
$doc = $dbForProject->upsertDocument(
$collectionId,
new Document($data),
);
$documentId is passed to the method and used for the "dependent" branch (row already touched earlier in the same transaction), but not here. main has the same code.
🎲 Appwrite version
2.3.0
💻 Operating system
Linux (Debian 12), Docker
🧱 Your Environment
Self-hosted Appwrite 2.3.0, Postgres adapter (PostgreSQL 18), two API nodes.
💡 Suggested fix
Set the ID before upserting, e.g. new Document(\array_merge($data, ['$id' => $documentId ?? $data['$id'] ?? ID::unique()])), and reject an operation where rowId and data.$id differ.
👀 Have you spent some time to check if this issue has been raised before?
- I checked and didn't find a similar issue
🏢 Have you read the Code of Conduct?
- I have read the Code of Conduct
- Lenguaje dominante
- PHP
- Estrellas
- 57.6k
- Forks
- 5.8k
- Merge medio
- 17 h 32 min
- PR fusionados (30 d)
- 397
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de appwrite/appwrite
-
Declare the Location header on OAuth2 redirect responses in the OpenAPI specPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abiertoproduct / auth product / databases product / messaging product / sites sdk / cli
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Los mantenedores suelen responder en 1 día
-
🐛 Bug Report: German translation (de.json) is missing 65 email keys, MFA code mail is EnglishAbiertoproduct / auth product / domains product / functions product / locale product / messaging product / sites product / storage
Dificultad 2/5 1-2 días Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día
-
🐛 Bug Report: Function executions with bodies > 1 MiB wait 2 s (`Expect: 100-continue`)Posiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abiertoproduct / databases product / functions product / self-hosted product / storage sdk / cli
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día
-
Calling `flush()` on a cache backed by the `Filesystem` adapter leads runtime failuresPosiblemente ocupada @cursor la tomó hace 6 días. Abiertoproduct / databases product / functions product / storage
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
appwrite/appwrite#14007 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Favicon uses the original page URL to resolve relative icon links after a redirectPosiblemente ocupada @Indra55 la tomó hace 7 días. Abiertoproduct / avatars product / self-hosted product / storage
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
appwrite/appwrite#13985 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de appwrite/appwrite
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
glpi-project/glpi#25842 ·
Los mantenedores suelen responder en 1 día
-
sync-en
Dificultad 1/5 Menos de una hora Aptitud para principiantes 83/100
Los mantenedores suelen responder en 1 día
-
sync-en
Dificultad 1/5 Menos de una hora Aptitud para principiantes 86/100
Los mantenedores suelen responder en 3 días
-
Перевод устарел
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
Los mantenedores suelen responder en 1 día