Skip to content

Throw BulkWriteException with write results on write errors#35

Open
premtsd-code wants to merge 3 commits intomainfrom
fix-bulk-write-exception
Open

Throw BulkWriteException with write results on write errors#35
premtsd-code wants to merge 3 commits intomainfrom
fix-bulk-write-exception

Conversation

@premtsd-code
Copy link
Copy Markdown
Contributor

@premtsd-code premtsd-code commented Apr 8, 2026

Summary

  • Throws BulkWriteException (already exists but was unused) instead of generic Exception when writeErrors are returned from MongoDB
  • Includes nInserted count and full writeErrors array in the exception result, accessible via $e->getResult()
  • Enables callers (e.g. utopia-php/database Mongo adapter) to recover partial success info from insertMany with ordered: false

Test plan

  • Added testInsertManyDuplicateThrowsBulkWriteException — verifies BulkWriteException is thrown with correct nInserted and writeErrors, and that non-duplicate docs persist with ordered: false
  • Existing tests pass (exception type is a subclass of Exception, so catches still work)

Summary by CodeRabbit

  • Bug Fixes
    • Improved bulk-write error handling to return detailed error information (message, code, error list) and operation stats (number of documents inserted).
  • Tests
    • Added a test covering unordered bulk inserts with duplicate keys, asserting detailed error payload and that non-duplicate documents are still persisted.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: be9e7d85-0ec0-4d96-9eff-49c04c89579b

📥 Commits

Reviewing files that changed from the base of the PR and between f1f106c and 56fe485.

📒 Files selected for processing (2)
  • src/Exception.php
  • tests/MongoTest.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/MongoTest.php

📝 Walkthrough

Walkthrough

Replaced generic exceptions with BulkWriteException on MongoDB bulk write errors in src/Client.php, enriched the exception with writeErrors and nInserted, adjusted BulkWriteException to forward write-error details to the base exception, and added a PHPUnit test validating the new behavior.

Changes

Cohort / File(s) Summary
Client bulk-write handling
src/Client.php
On detected MongoDB bulk write errors, throw BulkWriteException instead of generic Exception, providing message/code from the first writeError and a context array containing writeErrors and nInserted (from $result->n, default 0).
BulkWriteException forwarding
src/Exception.php
BulkWriteException::__construct now forwards writeErrors (and an empty errorLabels array) into the base Exception constructor so write-error details are carried into the parent exception state.
Test coverage
tests/MongoTest.php
Added testInsertManyDuplicateThrowsBulkWriteException() to assert insertMany() with ordered: false raises Utopia\Mongo\BulkWriteException (code 11000), contains nInserted and writeErrors in payload, and that non-duplicate documents were inserted; added import for BulkWriteException.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Feat client updates #28: Overlapping changes to src/Client.php and exception handling around BulkWriteException and src/Exception.php.

Suggested reviewers

  • abnegate

Poem

🐰 I hopped through writes both brave and quick,
Found duplicate gems that made me tick,
I packed the errors, counts in tow,
So tests can see what failed and what did grow,
Hooray — safe inserts in a tidy row ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.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 concisely describes the main change: throwing BulkWriteException instead of generic Exception when MongoDB write errors occur, with write results included.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-bulk-write-exception

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.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 8, 2026

Greptile Summary

This PR enhances error handling in bulk write operations by throwing BulkWriteException (instead of a generic Exception) when MongoDB returns writeErrors, and enriches the exception with the full writeErrors array and nInserted count via getResult(). This enables callers to recover partial success information from insertMany with ordered: false.

Key changes:

  • src/Client.php: parseResponse() now throws BulkWriteException with both writeErrors and nInserted (from $result->n) when writeErrors are present in the MongoDB response.
  • src/Exception.php: BulkWriteException::__construct() now forwards writeErrors to the parent Exception constructor, making getWriteErrors() functional on bulk write exceptions (previously it always returned null).
  • tests/MongoTest.php: Adds testInsertManyDuplicateThrowsBulkWriteException to verify the exception type, error code, nInserted, and that non-duplicate documents persist with ordered: false.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped, backwards-compatible (BulkWriteException extends Exception), and well-tested.

No P0 or P1 issues found. The exception type change is backwards-compatible since BulkWriteException extends Exception. The nInserted value correctly uses $result->n which is the MongoDB wire-protocol field for successfully inserted document count. The previously flagged weak assertion has been resolved with a precise assertSame(1, ...) check.

No files require special attention.

Vulnerabilities

No security concerns identified. The change only affects exception propagation and error data exposure within the library's own exception hierarchy — no user input is unsafely handled and no sensitive data is newly exposed.

Important Files Changed

Filename Overview
src/Client.php Throws BulkWriteException with writeErrors and nInserted ($result->n ?? 0) instead of a generic Exception on bulk write errors — logic is correct for ordered: false insert scenarios.
src/Exception.php Forwards writeErrors to the parent constructor so getWriteErrors() is now functional on BulkWriteException; clean fix that eliminates a latent inconsistency.
tests/MongoTest.php New integration test verifies BulkWriteException is thrown with correct code and result structure, and that non-duplicate documents persist; assertions are precise.

Reviews (2): Last reviewed commit: "Populate parent writeErrors in BulkWrite..." | Re-trigger Greptile

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
tests/MongoTest.php (1)

509-509: Tighten nInserted assertion to avoid false positives.

assertGreaterThanOrEqual(1, ...) can pass even if inserted count is wrong for this fixture (expected exactly 1).

Proposed test assertion tightening
-                self::assertGreaterThanOrEqual(1, $result['nInserted']);
+                self::assertSame(1, $result['nInserted']);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/MongoTest.php` at line 509, The current assertion uses
assertGreaterThanOrEqual(1, $result['nInserted']) which can produce false
positives; update the assertion to require exactly one inserted document by
replacing it with an equality check against $result['nInserted'] (e.g.,
assertSame(1, $result['nInserted']) or assertEquals(1, $result['nInserted'])) so
the test enforces the expected single insert.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/MongoTest.php`:
- Line 509: The current assertion uses assertGreaterThanOrEqual(1,
$result['nInserted']) which can produce false positives; update the assertion to
require exactly one inserted document by replacing it with an equality check
against $result['nInserted'] (e.g., assertSame(1, $result['nInserted']) or
assertEquals(1, $result['nInserted'])) so the test enforces the expected single
insert.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d6ebc86b-866f-4373-a791-3cb1a09c1454

📥 Commits

Reviewing files that changed from the base of the PR and between 677a21c and f1f106c.

📒 Files selected for processing (2)
  • src/Client.php
  • tests/MongoTest.php


$result = $e->getResult();
self::assertArrayHasKey('nInserted', $result);
self::assertArrayHasKey('writeErrors', $result);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Weak assertion on nInserted count

The assertion assertGreaterThanOrEqual(1, $result['nInserted']) would pass even if nInserted is 100. Since the setup inserts exactly two documents — one duplicate that must fail and one new one that must succeed — the count should be precisely 1 with ordered: false.

Suggested change
self::assertArrayHasKey('writeErrors', $result);
self::assertSame(1, $result['nInserted']);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Both fixed in 56fe485:

  • nInserted assertion tightened to assertSame(1, ...)
  • BulkWriteException now passes writeErrors to parent constructor, so getWriteErrors() is consistent with getResult()['writeErrors']

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 8, 2026

Tip:

Greploops — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.

Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

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