From 082d47c22ff68790e604b5ec18ec0b5537227734 Mon Sep 17 00:00:00 2001 From: deepshekhardas Date: Wed, 24 Jun 2026 12:23:56 +0530 Subject: [PATCH] fix: strip unknown internal attributes during migration Source (Appwrite.php): add to the list of stripped internal fields when exporting records, preventing it from leaking into row data. Destination (Appwrite.php): replace blind skip of all $-prefixed fields with an explicit allowlist of known internal attributes (, , , , , ). Unknown $-prefixed fields (e.g. from older sources, , , ) are now stripped before document creation, preventing Structure validator rejections. Fixes appwrite/appwrite#10265 --- src/Migration/Destinations/Appwrite.php | 4 ++++ src/Migration/Sources/Appwrite.php | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Migration/Destinations/Appwrite.php b/src/Migration/Destinations/Appwrite.php index 668f15eb..910f7e5e 100644 --- a/src/Migration/Destinations/Appwrite.php +++ b/src/Migration/Destinations/Appwrite.php @@ -1405,9 +1405,13 @@ protected function createRecord(Row $resource, bool $isLast): bool ); // Strip row payload fields the table doesn't declare — guards against orphans surviving in source archives. if ($dbForDatabases->getAdapter()->getSupportForAttributes()) { + $knownInternal = ['$id', '$permissions', '$collection', '$tenant', '$createdAt', '$updatedAt']; foreach ($this->rowBuffer as $row) { foreach ($row as $key => $value) { if (\str_starts_with($key, '$')) { + if (!\in_array($key, $knownInternal, true)) { + $row->removeAttribute($key); + } continue; } diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php index 4cf069ae..771913f3 100644 --- a/src/Migration/Sources/Appwrite.php +++ b/src/Migration/Sources/Appwrite.php @@ -1370,6 +1370,7 @@ private function exportRecords(string $entityName, string $fieldName, int $batch unset($row['$collection']); unset($row['$tableId']); unset($row['$table']); + unset($row['$internalId']); $row = self::getRecord($table->getDatabase()->getType(), [ 'id' => $id,