RocketChat/Rocket.Chat · warning · Error
error-e2e-key-reset-in-progress
Error message
error-e2e-key-reset-in-progress
What it means
Thrown by POST e2e.resetRoomKey when a key reset is already running for the same room: the endpoint guards concurrent resets with an in-module Map (LockMap) keyed by rid and throws new Error('error-e2e-key-reset-in-progress') if LockMap.has(rid). It is a per-process, in-memory lock, so it applies to concurrent calls on the same server instance and is released in a finally block when the reset finishes or fails.
Solutions
- Wait for the in-flight reset to finish (they are bounded by room size) and re-issue the request once.
- Debounce the reset button / serialize resets per room in the client so only one request is in flight.
- If the error persists long after any plausible reset duration, restart the Meteor server to clear a wedged LockMap entry.
Example fix
// before
await api.post('e2e.resetRoomKey', body); // user can double-fire
// after — one reset per room at a time, retry on in-progress
const inFlight = new Set();
async function resetRoomKey(rid, body) {
if (inFlight.has(rid)) return;
inFlight.add(rid);
try { await api.post('e2e.resetRoomKey', body); }
finally { inFlight.delete(rid); }
} Defensive patterns
Strategy: retry
Try / catch
for (let attempt = 1; attempt <= 5; attempt++) {
try { await api.post('e2e.resetRoomKey', body); break; }
catch (e) {
if (e.message !== 'error-e2e-key-reset-in-progress' || attempt === 5) throw e;
await delay(attempt * 1000); // prior reset still running for this rid
}
} Prevention
- Serialize resetRoomKey calls per room in the client (one in flight).
- Never bind the reset action to a control users can double-fire.
- If it never clears, suspect a wedged server-side lock and restart the app.
When it happens
Trigger: Two POST /api/v1/e2e.resetRoomKey requests for the same rid overlapping in time — e.g. a client retrying a slow reset, double-click on 'Reset key', or two sessions of the same user resetting simultaneously.
Common situations: Impatient users re-clicking during a long reset on a big room; frontend retry logic with a too-short timeout; parallel key-rotation scripts hitting the same room. Note a stuck lock (see the not-allowed path that throws after LockMap.set without cleanup) keeps producing this error until the server restarts.
Related errors
- error-not-allowed
- error-creating-custom-user-status
- error-invalid-param
- error-updatedSince-param-invalid
- error-updating-custom-user-status
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/59076c346931c2e5.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/e2e.ts:445
authRequired: true,
body: isE2EResetRoomKeyProps,
response: {
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
403: validateForbiddenErrorResponse,
200: ajv.compile<void>({
type: 'object',
}),
},
},
async function action() {
const { rid, e2eKey, e2eKeyId } = this.bodyParams;
if (!(await hasPermissionAsync(this.user, 'toggle-room-e2e-encryption', rid))) {
return API.v1.forbidden('error-not-allowed');
}
if (LockMap.has(rid)) {
throw new Error('error-e2e-key-reset-in-progress');
}
LockMap.set(rid, true);
if (!(await canAccessRoomIdAsync(rid, this.userId))) {
throw new Error('error-not-allowed');
}
try {
await resetRoomKey(rid, this.userId, e2eKey, e2eKeyId);
return API.v1.success();
} catch (e) {
console.error(e);
return API.v1.failure('error-e2e-key-reset-failed');
} finally {
LockMap.delete(rid);
}
},View on GitHub (pinned to b2c16d5842)