{"record":{"id":"655fda2843446500","repo":"pubkey/rxdb","slug":"col20","errorCode":"COL20","errorMessage":"\n        RxDB Error-Code: ${message}.\n        Hint: Error messages are not included in RxDB core to reduce build size.\n        To show the full error messages and to ensure that you do not make any mistakes when using RxDB,\n        use the dev-mode plugin when you are in development mode: https://rxdb.info/dev-mode.html?console=error\n        \nFind out more about this error here: https://rxdb.info/errors.html?console=errors#COL20 \nStill stuck? Ask in the RxDB Discord: https://rxdb.info/chat \n","messagePattern":"\n        RxDB Error-Code: \\$\\{message\\}\\.\n        Hint: Error messages are not included in RxDB core to reduce build size\\.\n        To show the full error messages and to ensure that you do not make any mistakes when using RxDB,\n        use the dev-mode plugin when you are in development mode: https://rxdb\\.info/dev-mode\\.html\\?console=error\n        \nFind out more about this error here: https://rxdb\\.info/errors\\.html\\?console=errors#COL20 \nStill stuck\\? Ask in the RxDB Discord: https://rxdb\\.info/chat \n","errorType":"error_code","errorClass":"RxError","httpStatus":null,"severity":"error","filePath":"src/rx-query.ts","lineNumber":511,"sourceCode":"    }\n\n    /**\n     * deletes all found documents\n     * @return promise with deleted documents\n     */\n    async remove(throwIfMissing?: boolean): Promise<RxQueryResult> {\n        if (throwIfMissing && this.op !== 'findOne') {\n            throw newRxError('QU9', {\n                collection: this.collection.name,\n                query: this.mangoQuery,\n                op: this.op\n            });\n        }\n        const docs = await this.exec();\n        if (Array.isArray(docs)) {\n            const result = await this.collection.bulkRemove(docs);\n            if (result.error.length > 0) {\n                throw rxStorageWriteErrorToRxError(result.error[0]);\n            } else {\n                return result.success as any;\n            }\n        } else if (docs instanceof Map) {\n            const docsArray = [...docs.values()];\n            const result = await this.collection.bulkRemove(docsArray as any);\n            if (result.error.length > 0) {\n                throw rxStorageWriteErrorToRxError(result.error[0]);\n            }\n            const resultMap = new Map();\n            result.success.forEach((doc: any) => resultMap.set(doc.primary, doc));\n            return resultMap as any;\n        } else {\n            // findOne() can return null when no document matches\n            if (!docs) {\n                if (throwIfMissing) {\n                    throw newRxError('QU10', {\n                        collection: this.collection.name,","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/pubkey/rxdb/blob/af6fb65f94cd70558d74c23799eda11ff1c15224/src/rx-query.ts#L493-L529","documentation":"remove() on a find() query executes the query, then calls collection.bulkRemove(). If any write in the bulk fails, the first storage write error is converted to a COL20 RxError and thrown. COL20 is RxDB's storage write error code, which typically wraps a conflict (409), a document not found, or a schema validation failure during the delete write.","triggerScenarios":"Calling find().remove() where at least one matched document was concurrently modified (revision conflict) or already deleted; a storage-level validation failure when writing the deletion marker; replication writing a newer revision between exec() and bulkRemove().","commonSituations":"Bulk-deleting documents while a replication or another tab updates them at the same time; deleting docs that are protected or whose schema changed; event-sourcing style collections with frequent concurrent writes.","solutions":["Inspect error.parameters.writeError / the wrapped 409 to see which document conflicted.","Re-run the query and remove again (delete your own snapshot of the docs), or delete per-document with doc.remove() and retry on conflict.","Resolve replication conflicts so local writes are not rejected (e.g. use doc.incrementalRemove())."],"exampleFix":"// before\nawait collection.find({ status: 'old' }).remove();\n// after (conflict-tolerant)\nconst docs = await collection.find({ status: 'old' }).exec();\nfor (const doc of docs) {\n  await doc.incrementalRemove(); // handles _rev conflicts\n}","handlingStrategy":"try-catch","validationCode":"const docs = await collection.find(selector).exec();\nfor (const doc of docs) {\n  if (!doc.deleted && doc.getLatest && doc) { /* doc still exists locally */ }\n}","typeGuard":"function isWriteConflict(err: any): boolean {\n  return err?.code === 'COL20' && (err?.parameters?.writeError?.status === 409 || err?.parameters?.status === 409);\n}","tryCatchPattern":"try {\n  await collection.find(selector).remove();\n} catch (err) {\n  if (err.code === 'COL20') {\n    const docs = await collection.find(selector).exec();\n    await Promise.all(docs.map(d => d.incrementalRemove())); // resolve conflicts\n  } else { throw err; }\n}","preventionTips":["Prefer doc.incrementalRemove() when concurrent replication writes are possible.","Do not hold query results for a long time before bulk-removing; re-exec instead.","Set a conflict handler on the collection that resolves deletes deterministically."],"tags":["write-conflict","bulk-remove","storage"],"backgroundTag":"write-conflict-409","analyzedSha":"af6fb65f94cd70558d74c23799eda11ff1c15224","analyzedAt":"2026-08-31T23:32:37.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}