RocketChat/Rocket.Chat · warning · Meteor.Error
too-many-requests
too-many-requests
Error message
DDPRateLimiter.getErrorMessage(rateLimitResult)
What it means
Thrown by POST /api/v1/method.call/:method when DDPRateLimiter._check(rateLimiterInput) returns allowed: false. This endpoint proxies a Meteor method invocation over REST and applies DDP rate limiting per user, IP, method name, and connection ID. The error message is generated by DDPRateLimiter.getErrorMessage(rateLimitResult) and the timeToReset timestamp is included in the error metadata.
Source
Thrown at apps/meteor/server/api/v1/misc.ts:666
this.token ||
crypto
.createHash('sha256')
.update((this.requestIp ?? '') + this.user._id)
.digest('hex');
const rateLimiterInput = {
userId: this.userId,
clientAddress: this.requestIp,
type: 'method',
name: method,
connectionId,
};
try {
DDPRateLimiter._increment(rateLimiterInput);
const rateLimitResult = DDPRateLimiter._check(rateLimiterInput);
if (!rateLimitResult.allowed) {
throw new Meteor.Error('too-many-requests', DDPRateLimiter.getErrorMessage(rateLimitResult), {
timeToReset: rateLimitResult.timeToReset,
});
}
return API.v1.success(mountResult({ id, result: await Meteor.callAsync(method, ...params) }));
} catch (err) {
if (!(err as any).isClientSafe && !(err as any).meteorError) {
SystemLogger.error({ msg: 'Exception while invoking method', err, method });
}
if (settings.get('Log_Level') === '2') {
Meteor._debug(`Exception while invoking method ${method}`, err);
}
return API.v1.failure(mountResult({ id, error: err }));
}
},
);View on GitHub (pinned to f9d3ec372b)
Solutions
- Reduce call frequency — implement exponential backoff and respect the timeToReset value in the error response.
- Check if the method has a custom rate limit rule via DDPRateLimiter and consider raising the limit if appropriate.
- Batch multiple operations into a single method call if the method supports it.
- Use the buffered variant (method.callBulk) to reduce individual request counts.
Example fix
// before: rapid polling
setInterval(() => callMethod('getUserStatus'), 100);
// after: respect rate limit
async function callWithBackoff(method) {
try { return await api.callMethod(method); }
catch (e) {
if (e.error === 'too-many-requests') {
const reset = e.details?.timeToReset || 5000;
await sleep(reset);
return callWithBackoff(method);
}
throw e;
}
} Defensive patterns
Strategy: retry
Validate before calling
// Implement a token-bucket or fixed-window throttle client-side before calling method.call
const MIN_INTERVAL_MS = 200; // adjust based on known rate limits
let lastCall = 0;
async function throttledMethodCall(method, params) {
const now = Date.now();
const elapsed = now - lastCall;
if (elapsed < MIN_INTERVAL_MS) {
await new Promise(r => setTimeout(r, MIN_INTERVAL_MS - elapsed));
}
lastCall = Date.now();
return callMethod(method, params);
} Try / catch
try {
return await callMethodOverRest(method, params);
} catch (e) {
if (e.error === 'too-many-requests') {
const timeToReset = e.details?.timeToReset ?? 5000;
await new Promise(r => setTimeout(r, timeToReset));
return callMethodOverRest(method, params); // retry once
}
throw e;
} Prevention
- Throttle method.call requests client-side to stay under DDP rate limits.
- Always read and respect the timeToReset value from the error response before retrying.
- Use exponential backoff for retries rather than immediate re-submission.
- Prefer WebSocket DDP connections over REST method.call for high-frequency method calls.
When it happens
Trigger: Calling POST /api/v1/method.call/:method (authenticated) repeatedly fast enough to exceed the DDP rate limit rule for that specific method. The rate limit is keyed on userId, clientAddress, method name, and connectionId.
Common situations: A polling loop or retry mechanism calling the same method too rapidly; admin tightened the DDP rate limit rules for a specific method; multiple clients sharing a single NAT IP; a bot or integration making many sequential method calls without throttling.
Related errors
- Invalid Api parameter provided, it must be a valid IApi obje
- error-emoji-param-not-provided
- error-param-required
- error-lastUpdate-param-invalid
- error-roomId-param-not-provided
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/030c3a6dfde1ad74.
Report an issue: GitHub.