From 2670b6578f6df0fa4234a2963d7e9fc89e1a6508 Mon Sep 17 00:00:00 2001 From: Pierre Brisorgueil Date: Thu, 4 Jun 2026 17:42:36 +0200 Subject: [PATCH] docs(errors): document mongoose.model() init-order time bomb in standalone scripts Closes #3789 --- ERRORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ERRORS.md b/ERRORS.md index a0e11a907..509d8a2f4 100644 --- a/ERRORS.md +++ b/ERRORS.md @@ -28,3 +28,4 @@ Use this file as a compact memory of recurring AI mistakes. - [2026-03-15] pr scope: batching multiple unrelated fixes in one PR -> one fix = one PR to isolate blast radius and reduce iteration loops - [2026-05-05] repository: Repository.update(doc) doing `new Model(doc).save()` rewrites the full document from in-memory state, silently clobbering any concurrent partial update that landed after the read -> always use `Model.updateOne({ _id }, { $set: ... })` or `findOneAndUpdate({ _id }, { $set: ... })` for partial updates to avoid race conditions; see comes-io/trawl_node#1115 comes-io/trawl_node#1116 comes-io/trawl_node#1118 + pierreb-devkit/Node#3605 - [2026-05-31] billing/stripe: reading `price.metadata.planId` in `customer.subscription.updated` webhook handler -> field is EMPTY in real Stripe webhook payloads (planId lives on the Product, not the Price); use a `priceId → plan` map built at boot from `config.stripe.prices` instead; see pierreb-devkit/Node#3742 +- [2026-06-04] repository: top-level `const Foo = mongoose.model('Foo')` in a repository file -> this is evaluated at import time; safe in an HTTP server (loadModels() runs first) but silently crashes standalone scripts (crons, migrations) with `MissingSchemaError` when import order differs; tests miss it because jest mocks intercept the module entirely; fix = lazy getter `const Foo = () => mongoose.model('Foo')` (call sites: `Foo().find(...)`) or dynamic import after `loadModels()` in the entrypoint; see comes-io/trawl_node#1337 comes-io/trawl_node#1338 pierreb-devkit/Node#3789