Skip to content

Downgrade missing required CSV column from exception to warning#159

Open
claudear wants to merge 1 commit intomainfrom
fix/csv-missing-required-column-warning
Open

Downgrade missing required CSV column from exception to warning#159
claudear wants to merge 1 commit intomainfrom
fix/csv-missing-required-column-warning

Conversation

@claudear
Copy link

@claudear claudear commented Mar 11, 2026

Summary

  • When a CSV file is missing columns marked as required in the database schema (e.g., a column named texte), the CSV importer was throwing a hard exception that blocked the entire import and generated Sentry errors.
  • Changed validateCSVHeaders to log a warning instead of throwing an exception for missing required columns. The import proceeds and the database layer enforces constraints per-row, providing better error granularity.
  • Added unit tests for the new warning behavior and for verifying no false warnings when all required columns are present.

Fixes: https://appwrite.sentry.io/issues/7326827048/

Test plan

  • New test testValidateCSVHeadersMissingRequiredColumnIsWarning verifies missing required columns produce a warning (not an exception)
  • New test testValidateCSVHeadersAllRequiredPresent verifies no false warnings when all required columns exist
  • All existing CSV unit tests continue to pass
  • Verify in production that CSV imports with missing required columns no longer generate Sentry errors

🤖 Generated with Claude Code

Summary by CodeRabbit

Bug Fixes

  • CSV validation workflow updated: missing required headers and unknown columns are now reported as warnings instead of exceptions; database-level constraints enforce integrity during row processing

Tests

  • Added comprehensive unit tests for CSV header validation scenarios, including detection of missing required columns and proper validation when all required headers are present

When a CSV file is missing columns marked as required in the database
schema, the import now logs a warning instead of throwing an exception.
This allows the import to proceed and lets the database layer enforce
constraints per-row, rather than blocking the entire import.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 11, 2026

Walkthrough

This pull request modifies CSV header validation in the migration source to shift from exception-based to warning-based signaling. Missing required headers and unknown columns are now logged as warnings instead of throwing exceptions, deferring constraint enforcement to the database layer. Additionally, two new unit tests are added to verify the warning behavior of the private validateCSVHeaders method using reflection.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and specifically describes the main change: converting missing required CSV column handling from exception-based to warning-based approach.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/csv-missing-required-column-warning

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/Migration/Unit/General/CSVTest.php`:
- Around line 450-472: The test testValidateCSVHeadersAllRequiredPresent is too
loose: tighten it by initializing the instance->resourceId (like the other test)
before invoking validateCSVHeaders, and assert exactly that there are no
warnings emitted (e.g., assertEmpty or assertCount(0) on $instance->warnings)
rather than scanning for a specific message; this ensures any unexpected warning
(including unknown-header or other regressions) fails the test and avoids false
positives. Reference: CSV::validateCSVHeaders,
CSVTest::testValidateCSVHeadersAllRequiredPresent and the
instance->warnings/resourceId fields.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2fe540a4-6ddf-47d2-90ba-265bf0dc7ef4

📥 Commits

Reviewing files that changed from the base of the PR and between bbdd8ef and 7024a59.

📒 Files selected for processing (2)
  • src/Migration/Sources/CSV.php
  • tests/Migration/Unit/General/CSVTest.php

Comment on lines +450 to +472
public function testValidateCSVHeadersAllRequiredPresent(): void
{
$reflection = new \ReflectionClass(CSV::class);
$instance = $reflection->newInstanceWithoutConstructor();

$refMethod = $reflection->getMethod('validateCSVHeaders');
$refMethod->setAccessible(true);

$headers = ['name', 'age', 'texte'];
$columnTypes = ['name' => 'string', 'age' => 'integer', 'texte' => 'string'];
$requiredColumns = ['texte' => true];

// Should not throw and not add warnings for required columns
$refMethod->invoke($instance, $headers, $columnTypes, $requiredColumns);

// No warnings about missing required columns (may have unknown column warnings)
$hasRequiredWarning = false;
foreach ($instance->warnings as $warning) {
if (str_contains($warning->getMessage(), 'Missing required')) {
$hasRequiredWarning = true;
}
}
$this->assertFalse($hasRequiredWarning, 'No warning should be added when all required columns are present');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Tighten this “no false warnings” test.

With these inputs there are no unknown headers either, so any warning is a regression. The current assertion would still pass if validateCSVHeaders() started emitting some other warning. Also, initialize resourceId here like the previous test so an unexpected warning path fails as an assertion, not via uninitialized state.

Suggested test hardening
 public function testValidateCSVHeadersAllRequiredPresent(): void
 {
     $reflection = new \ReflectionClass(CSV::class);
     $instance = $reflection->newInstanceWithoutConstructor();
+
+    $resourceIdProp = $reflection->getProperty('resourceId');
+    $resourceIdProp->setAccessible(true);
+    $resourceIdProp->setValue($instance, 'testdb:testtable');

     $refMethod = $reflection->getMethod('validateCSVHeaders');
     $refMethod->setAccessible(true);

     $headers = ['name', 'age', 'texte'];
     $columnTypes = ['name' => 'string', 'age' => 'integer', 'texte' => 'string'];
     $requiredColumns = ['texte' => true];

-    // Should not throw and not add warnings for required columns
+    // Should not throw and should not add warnings
     $refMethod->invoke($instance, $headers, $columnTypes, $requiredColumns);

-    // No warnings about missing required columns (may have unknown column warnings)
-    $hasRequiredWarning = false;
-    foreach ($instance->warnings as $warning) {
-        if (str_contains($warning->getMessage(), 'Missing required')) {
-            $hasRequiredWarning = true;
-        }
-    }
-    $this->assertFalse($hasRequiredWarning, 'No warning should be added when all required columns are present');
+    $this->assertEmpty($instance->warnings, 'No warning should be added when all headers are valid');
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Migration/Unit/General/CSVTest.php` around lines 450 - 472, The test
testValidateCSVHeadersAllRequiredPresent is too loose: tighten it by
initializing the instance->resourceId (like the other test) before invoking
validateCSVHeaders, and assert exactly that there are no warnings emitted (e.g.,
assertEmpty or assertCount(0) on $instance->warnings) rather than scanning for a
specific message; this ensures any unexpected warning (including unknown-header
or other regressions) fails the test and avoids false positives. Reference:
CSV::validateCSVHeaders, CSVTest::testValidateCSVHeadersAllRequiredPresent and
the instance->warnings/resourceId fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant