Skip to content

fix(injectModel): fix pre-existing index rollback and required-field duplicate precheck#75

Merged
Shivkumardhakad merged 2 commits intomainfrom
copilot/fix-pre-existing-index-rollback
Apr 8, 2026
Merged

fix(injectModel): fix pre-existing index rollback and required-field duplicate precheck#75
Shivkumardhakad merged 2 commits intomainfrom
copilot/fix-pre-existing-index-rollback

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 2, 2026

Two edge-case bugs in createUniqueIndexes and getUniqueFieldFilter that could cause silent data loss and missed duplicate detection on live collections.

Changes

  • Rollback safety (createUniqueIndexes): Snapshot existing index names before the loop; only push indexes into createdIndexes if they weren't already present. The rollback path now exclusively drops indexes created by the current operation, preventing accidental destruction of pre-existing indexes when a later field fails.
const existingIndexNames = new Set((await Model.collection.indexes()).map(i => i.name));
// ...
const createdName = await Model.collection.createIndex({ [normalizedKey]: 1 }, indexOptions);
if (!existingIndexNames.has(createdName)) createdIndexes.push(createdName);
  • Required-field duplicate precheck (getUniqueFieldFilter): For required fields, return {} instead of { [fieldKey]: { $exists: true } }. MongoDB's unique index treats all missing-field documents as duplicate nulls, so the old filter could pass the precheck while createIndex still throws error 11000.
function getUniqueFieldFilter(fieldKey, isRequired) {
  if (isRequired) return {}; // include missing-field docs
  return { [fieldKey]: { $exists: true, $ne: null } };
}

Summary by CodeRabbit

  • Bug Fixes
    • Refined duplicate detection filtering to correctly include all documents during the validation process, ensuring comprehensive duplicate detection across all records.
    • Enhanced index creation with improved error handling, automatic cleanup of partially created indexes on failure, and intelligent detection of pre-existing indexes to prevent redundant index creation.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ur-backend-web-dashboard Ready Ready Preview, Comment Apr 2, 2026 8:23pm

…duplicate precheck

Agent-Logs-Url: https://github.com/yash-pouranik/urBackend/sessions/a4ebb02d-93e3-4686-9938-d19a6344dc1a

Co-authored-by: yash-pouranik <172860064+yash-pouranik@users.noreply.github.com>
@yash-pouranik yash-pouranik temporarily deployed to copilot/fix-pre-existing-index-rollback - urBackend-frankfrut PR #75 April 2, 2026 20:23 — with Render Destroyed
Copilot AI changed the title [WIP] Fix pre-existing index rollback and required-field duplicate precheck fix(injectModel): fix pre-existing index rollback and required-field duplicate precheck Apr 2, 2026
@yash-pouranik yash-pouranik marked this pull request as ready for review April 2, 2026 20:43
Copilot AI review requested due to automatic review settings April 2, 2026 20:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes two edge cases in the dynamic model injection utilities to prevent unsafe index rollback and improve duplicate detection before creating MongoDB unique indexes.

Changes:

  • Make unique-index rollback safe by tracking only indexes newly created during the current createUniqueIndexes run.
  • Adjust required-field duplicate precheck to include documents missing the field (aligning with MongoDB unique-index behavior for missing values).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


throw new Error(
`Cannot create unique index on '${normalizedKey}'. ${duplicates.length} duplicate values exist.${examples ? ` Examples: ${examples}` : ""}`,
const existingIndexes = await Model.collection.indexes();
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

Model.collection.indexes() will throw a NamespaceNotFound (code 26 / "ns not found") error when the collection doesn’t exist yet. createUniqueIndexes is called immediately after compiling a model for newly-created collections (before any inserts), so this can cause schema/collection creation to fail before any indexes are created. Consider wrapping the indexes() call in a try/catch and treating NamespaceNotFound as an empty index list (or ensuring the collection exists via Model.createCollection() / Model.init() before calling indexes()).

Suggested change
const existingIndexes = await Model.collection.indexes();
let existingIndexes = [];
try {
existingIndexes = await Model.collection.indexes();
} catch (err) {
const isNamespaceNotFound =
err &&
(err.code === 26 ||
err.codeName === "NamespaceNotFound" ||
err.message === "ns not found" ||
(typeof err.message === "string" &&
err.message.toLowerCase().includes("ns not found")));
if (!isNamespaceNotFound) {
throw err;
}
}

Copilot uses AI. Check for mistakes.
@Shivkumardhakad
Copy link
Copy Markdown
Collaborator

@coderabbitai merge??

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 8, 2026

Tip

For best results, initiate chat on the files or code changes.

@Shivkumardhakad, I'm afraid merging pull requests is outside my capabilities — only repository maintainers can do that through GitHub's UI or CLI.

However, if you'd like me to approve this PR, just say @coderabbitai approve and I'll take care of that for you. 🐇


🧠 Learnings used
Learnt from: CR
Repo: geturbackend/urBackend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-08T10:39:32.900Z
Learning: When changing collection behavior, verify: schema validation in `packages/common`, model compilation in `packages/common/src/utils/injectModel.js`, dashboard create collection UI, and dashboard-api collection creation/index creation flow.

@Shivkumardhakad
Copy link
Copy Markdown
Collaborator

Bro @coderabbitai I mean is this PR OK to merge? please review?
against Main branch

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 8, 2026

@Shivkumardhakad, sure! Let me do a full review of this PR against the main branch right now. I'll check the rollback safety fix in createUniqueIndexes and the required-field duplicate precheck fix in getUniqueFieldFilter, as well as any downstream impacts on schema validation and the dashboard-api flow. Hang tight! 🐇


🧠 Learnings used
Learnt from: CR
Repo: geturbackend/urBackend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-08T10:39:32.900Z
Learning: When changing collection behavior, verify: schema validation in `packages/common`, model compilation in `packages/common/src/utils/injectModel.js`, dashboard create collection UI, and dashboard-api collection creation/index creation flow.
✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

Modified injectModel.js to adjust field filtering logic for required fields in duplicate detection and enhance index creation robustness by tracking existing indexes, implementing rollback on failure, and avoiding redundant index creation attempts.

Changes

Cohort / File(s) Summary
Index Creation & Field Filtering Logic
packages/common/src/utils/injectModel.js
Updated getUniqueFieldFilter() to return empty match filter when field is required, including documents with missing fields. Refactored createUniqueIndexes() to track successfully created and pre-existing index names, wrap creation in try/catch with rollback on error, and skip re-creating existing indexes.

Possibly related issues

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hopping through indexes with care,
Tracking what's new, what was there,
When required fields dance and sway,
We include them all come what may,
No more re-creating the old—
Our rollback strategy is gold!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 describes both main fixes: pre-existing index rollback safety and required-field duplicate precheck handling in getUniqueFieldFilter.

✏️ 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 copilot/fix-pre-existing-index-rollback

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
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)
packages/common/src/utils/injectModel.js (1)

224-228: Consider logging rollback failures for debugging visibility.

The current .catch(() => {}) pattern is fine for ensuring cleanup continues, but silently swallowed errors may complicate debugging if rollback partially fails.

💡 Optional: Add minimal logging for rollback failures
   } catch (err) {
     for (const indexName of createdIndexes) {
-      await Model.collection.dropIndex(indexName).catch(() => {});
+      await Model.collection.dropIndex(indexName).catch((dropErr) => {
+        console.warn(`Failed to rollback index ${indexName}:`, dropErr.message);
+      });
     }
     throw err;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/common/src/utils/injectModel.js` around lines 224 - 228, The
rollback catch currently swallows dropIndex errors; update the cleanup loop in
the catch block that iterates over createdIndexes and calls
Model.collection.dropIndex(indexName) so that failures are logged (e.g., include
indexName and the error) instead of being silently ignored—use a minimal logger
(console.warn or the module's existing logger) inside the .catch handler for
Model.collection.dropIndex to record rollback failures while still allowing the
loop to continue and rethrow the original err at the end.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/common/src/utils/injectModel.js`:
- Around line 224-228: The rollback catch currently swallows dropIndex errors;
update the cleanup loop in the catch block that iterates over createdIndexes and
calls Model.collection.dropIndex(indexName) so that failures are logged (e.g.,
include indexName and the error) instead of being silently ignored—use a minimal
logger (console.warn or the module's existing logger) inside the .catch handler
for Model.collection.dropIndex to record rollback failures while still allowing
the loop to continue and rethrow the original err at the end.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4990db98-8d40-4f9c-9499-23643ea5140b

📥 Commits

Reviewing files that changed from the base of the PR and between a782604 and c7b7371.

📒 Files selected for processing (1)
  • packages/common/src/utils/injectModel.js

@Shivkumardhakad Shivkumardhakad merged commit c9a6b9b into main Apr 8, 2026
10 checks passed
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.

fix(injectModel): fix pre-existing index rollback and required-field duplicate precheck

4 participants