pubkey/rxdb · error · RxError

COL20

COL20

Error message

        RxDB Error-Code: ${message}.
        Hint: Error messages are not included in RxDB core to reduce build size.
        To show the full error messages and to ensure that you do not make any mistakes when using RxDB,
        use the dev-mode plugin when you are in development mode: https://rxdb.info/dev-mode.html?console=error
        
Find out more about this error here: https://rxdb.info/errors.html?console=errors#COL20 
Still stuck? Ask in the RxDB Discord: https://rxdb.info/chat 

What it means

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.

Source

Thrown at src/rx-query.ts:511

    }

    /**
     * deletes all found documents
     * @return promise with deleted documents
     */
    async remove(throwIfMissing?: boolean): Promise<RxQueryResult> {
        if (throwIfMissing && this.op !== 'findOne') {
            throw newRxError('QU9', {
                collection: this.collection.name,
                query: this.mangoQuery,
                op: this.op
            });
        }
        const docs = await this.exec();
        if (Array.isArray(docs)) {
            const result = await this.collection.bulkRemove(docs);
            if (result.error.length > 0) {
                throw rxStorageWriteErrorToRxError(result.error[0]);
            } else {
                return result.success as any;
            }
        } else if (docs instanceof Map) {
            const docsArray = [...docs.values()];
            const result = await this.collection.bulkRemove(docsArray as any);
            if (result.error.length > 0) {
                throw rxStorageWriteErrorToRxError(result.error[0]);
            }
            const resultMap = new Map();
            result.success.forEach((doc: any) => resultMap.set(doc.primary, doc));
            return resultMap as any;
        } else {
            // findOne() can return null when no document matches
            if (!docs) {
                if (throwIfMissing) {
                    throw newRxError('QU10', {
                        collection: this.collection.name,

View on GitHub (pinned to af6fb65f94)

Solutions

  1. Inspect error.parameters.writeError / the wrapped 409 to see which document conflicted.
  2. 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.
  3. Resolve replication conflicts so local writes are not rejected (e.g. use doc.incrementalRemove()).

Example fix

// before
await collection.find({ status: 'old' }).remove();
// after (conflict-tolerant)
const docs = await collection.find({ status: 'old' }).exec();
for (const doc of docs) {
  await doc.incrementalRemove(); // handles _rev conflicts
}
Defensive patterns

Strategy: try-catch

Validate before calling

const docs = await collection.find(selector).exec();
for (const doc of docs) {
  if (!doc.deleted && doc.getLatest && doc) { /* doc still exists locally */ }
}

Type guard

function isWriteConflict(err: any): boolean {
  return err?.code === 'COL20' && (err?.parameters?.writeError?.status === 409 || err?.parameters?.status === 409);
}

Try / catch

try {
  await collection.find(selector).remove();
} catch (err) {
  if (err.code === 'COL20') {
    const docs = await collection.find(selector).exec();
    await Promise.all(docs.map(d => d.incrementalRemove())); // resolve conflicts
  } else { throw err; }
}

Prevention

When it happens

Trigger: 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().

Common situations: 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.

Related errors


AI-assisted analysis of pubkey/rxdb@af6fb65f94 (2026-08-31). Data as JSON: /api/errors/655fda2843446500. Report an issue: GitHub.