meteor/meteor · error · Error
Please specify only one of removed() and removedAt()
Error message
Please specify only one of removed() and removedAt()
What it means
Thrown by LocalCollection._observeCallbacksAreOrdered when both 'removed' (unordered) and 'removedAt' (ordered, with index) are present on the observe callbacks object. Same mutually-exclusive ordered/unordered contract as the added and changed pairs.
Source
Thrown at packages/minimongo/local_collection.js:1695
if (Meteor._isPromise(handle)) {
handle.then(setSuppressed);
} else {
setSuppressed(handle);
}
return handle;
};
LocalCollection._observeCallbacksAreOrdered = callbacks => {
if (callbacks.added && callbacks.addedAt) {
throw new Error('Please specify only one of added() and addedAt()');
}
if (callbacks.changed && callbacks.changedAt) {
throw new Error('Please specify only one of changed() and changedAt()');
}
if (callbacks.removed && callbacks.removedAt) {
throw new Error('Please specify only one of removed() and removedAt()');
}
return !!(
callbacks.addedAt ||
callbacks.changedAt ||
callbacks.movedTo ||
callbacks.removedAt
);
};
LocalCollection._observeChangesCallbacksAreOrdered = callbacks => {
if (callbacks.added && callbacks.addedBefore) {
throw new Error('Please specify only one of added() and addedBefore()');
}
return !!(callbacks.addedBefore || callbacks.movedBefore);
};
View on GitHub (pinned to 5076d2f818)
Solutions
- Pick ordered or unordered and keep only that set of remove callbacks.
- Keep removedAt(doc, idx) if you need to know the document's former position; otherwise keep removed(doc).
- Audit the callbacks object for all three pairs (added/addedAt, changed/changedAt, removed/removedAt) since the guard runs against each.
- Add a unit test asserting no conflicting callback pair is set.
Example fix
// before
users.find().observe({ removedAt(doc, idx) {}, removed(doc) {} });
// after
users.find().observe({ removedAt(doc, idx) {} }); Defensive patterns
Strategy: validation
Validate before calling
function assertNoRemovedPair(cb) {
if (cb && cb.removed && cb.removedAt) {
throw new TypeError('Choose removed (unordered) OR removedAt (ordered), not both');
}
return cb;
}
cursor.observe(assertNoRemovedPair(callbacks)); Type guard
function hasConflictingRemovedPair(cb) {
return !!(cb && cb.removed && cb.removedAt);
} Prevention
- Build observe callbacks through one factory so the ordered/unordered choice is made once.
- Static-check the callbacks object shape in a unit test.
- When merging two callback objects, assert no conflicting pair results.
When it happens
Trigger: Passing cursor.observe({ removed() {...}, removedAt(doc, idx) {...} }) — both keys truthy at observe setup time triggers the synchronous guard.
Common situations: Copying a removed handler from an unordered example into an already-ordered observe callbacks object; auto-generating callbacks from a schema where both forms are defined.
Related errors
- Please specify only one of added() and addedAt()
- Please specify only one of changed() and changedAt()
- Please specify only one of added() and addedBefore()
- Invalid selector: ${selector}
- ${allowOrDeny}: Invalid key: ${key}
AI-assisted analysis of meteor/meteor@5076d2f818 (2026-08-13).
Data as JSON: /api/errors/d41252660d0850a6.
Report an issue: GitHub.