From 074e562f3cb92fc6a6cc06fa720a52d14405455a Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Wed, 7 Oct 2026 14:59:24 +0530 Subject: [PATCH] fix: keep documents with a null required attribute updatable A document stored before an attribute became required holds null for it, and updates validate the merged document, so every update of that document failed with "Missing required attribute". When the current document already holds null, the attribute may stay null on update. Creating a document without it, or clearing a stored value, still fails. --- src/Database/Validator/Structure.php | 9 ++++++++ tests/unit/Validator/StructureTest.php | 32 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/Database/Validator/Structure.php b/src/Database/Validator/Structure.php index 4e3f66ec4b..22f31a57f7 100644 --- a/src/Database/Validator/Structure.php +++ b/src/Database/Validator/Structure.php @@ -267,6 +267,11 @@ protected function checkForAllRequiredValues(array $structure, array $attributes $keys[$name] = $attribute; // List of allowed attributes to help find unknown ones if ($required && !isset($structure[$name])) { + // Documents stored before the attribute became required hold null, and may keep it + if ($this->currentDocument !== null && $this->currentDocument->getAttribute($name) === null) { + continue; + } + $this->message = 'Missing required attribute "'.$name.'"'; return false; } @@ -333,6 +338,10 @@ protected function checkForInvalidAttributeValues(Document $document, array $str continue; } + if (is_null($value) && $this->currentDocument !== null && $this->currentDocument->getAttribute($key) === null) { + continue; + } + if ($type === Database::VAR_RELATIONSHIP) { continue; } diff --git a/tests/unit/Validator/StructureTest.php b/tests/unit/Validator/StructureTest.php index 71c90577cb..e82a1cae56 100644 --- a/tests/unit/Validator/StructureTest.php +++ b/tests/unit/Validator/StructureTest.php @@ -242,6 +242,38 @@ public function testRequiredKeys(): void $this->assertEquals('Invalid document structure: Missing required attribute "title"', $validator->getDescription()); } + public function testRequiredKeyStoredAsNull(): void + { + $document = [ + '$collection' => ID::custom('posts'), + 'description' => 'Demo description', + 'rating' => 5, + 'price' => 1.99, + 'published' => true, + 'feedback' => 'team@appwrite.io', + '$createdAt' => '2000-04-01T12:00:00.000+00:00', + '$updatedAt' => '2000-04-01T12:00:00.000+00:00' + ]; + + $validator = new Structure( + new Document($this->collection), + Database::VAR_INTEGER, + currentDocument: new Document(['title' => null]) + ); + + $this->assertTrue($validator->isValid(new Document($document)), $validator->getDescription()); + $this->assertTrue($validator->isValid(new Document([...$document, 'title' => null])), $validator->getDescription()); + + $validator = new Structure( + new Document($this->collection), + Database::VAR_INTEGER, + currentDocument: new Document(['title' => 'My Title']) + ); + + $this->assertFalse($validator->isValid(new Document([...$document, 'title' => null]))); + $this->assertEquals('Invalid document structure: Missing required attribute "title"', $validator->getDescription()); + } + public function testNullValues(): void { $validator = new Structure(