nextcloud/server · error · TooManyRequests
Too many calendars created
Error message
Too many calendars created
What it means
Thrown by the CalDAV RateLimitingPlugin, which hooks the Sabre 'beforeBind' event and fires whenever a new calendar or subscription is created at a path like calendars/<user>/<name>. It calls the OC rate limiter with the identifier 'caldav-create-calendar', the app config rateLimitCalendarCreation (default 10) and rateLimitPeriodCalendarCreation (default 3600 seconds), and converts the resulting RateLimitExceededException into a TooManyRequests DAV exception (HTTP 429). It is an anti-flood guard so one authenticated user cannot create unbounded calendars in a short window.
Source
Thrown at apps/dav/lib/CalDAV/Security/RateLimitingPlugin.php:64
}
$user = $this->userManager->get($this->userId);
if ($user === null) {
// We only care about authenticated users here
return;
}
$pathParts = explode('/', $path);
if (count($pathParts) === 3 && $pathParts[0] === 'calendars') {
// Path looks like calendars/username/calendarname so a new calendar or subscription is created
try {
$this->limiter->registerUserRequest(
'caldav-create-calendar',
$this->config->getValueInt('dav', 'rateLimitCalendarCreation', 10),
$this->config->getValueInt('dav', 'rateLimitPeriodCalendarCreation', 3600),
$user
);
} catch (RateLimitExceededException $e) {
throw new TooManyRequests('Too many calendars created', 0, $e);
}
$calendarLimit = $this->config->getValueInt('dav', 'maximumCalendarsSubscriptions', 30);
if ($calendarLimit === -1) {
return;
}
$numCalendars = $this->calDavBackend->getCalendarsForUserCount('principals/users/' . $user->getUID());
$numSubscriptions = $this->calDavBackend->getSubscriptionsForUserCount('principals/users/' . $user->getUID());
if (($numCalendars + $numSubscriptions) >= $calendarLimit) {
$this->logger->warning('Maximum number of calendars/subscriptions reached', [
'calendars' => $numCalendars,
'subscription' => $numSubscriptions,
'limit' => $calendarLimit,
]);
throw new Forbidden('Calendar limit reached', 0);
}
}View on GitHub (pinned to ecdeb153ff)
Solutions
- Space out or queue calendar creations and wait for the period (default 3600 s) to elapse before retrying
- Raise the limit for the affected instance: occ config:app:set dav rateLimitCalendarCreation --value 100
- Shrink the measurement window if a short burst is legitimate: occ config:app:set dav rateLimitPeriodCalendarCreation --value 600
- For bulk provisioning, bypass HTTP and use CalDavBackend/occ tooling server-side instead of repeated MKCALENDAR requests
Example fix
// before: tight loop hitting the CalDAV endpoint
foreach ($names as $name) {
$client->request('MKCALENDAR', "/remote.php/dav/calendars/$user/$name/");
}
// after: throttle client-side and back off on 429
$created = 0;
foreach ($names as $name) {
if ($created >= 10) { sleep(3600); $created = 0; }
$resp = $client->request('MKCALENDAR', "/remote.php/dav/calendars/$user/$name/");
if ($resp->getStatus() === 429) { sleep(3600); continue; }
$created++;
} Defensive patterns
Strategy: retry
Validate before calling
// Client-side sliding-window counter before any MKCALENDAR
const WINDOW_MS = 3600_000, MAX = 10; // mirror dav defaults
const stamps = [];
function mayCreateCalendar() {
const now = Date.now();
while (stamps.length && now - stamps[0] > WINDOW_MS) stamps.shift();
return stamps.length < MAX;
} Try / catch
try {
await client.mkCalendar(`/remote.php/dav/calendars/${user}/${name}/`);
} catch (e) {
if (e.status === 429) {
// honor the configured period (default 3600 s) before retrying
await sleep(rateLimitPeriodCalendarCreationMs);
return client.mkCalendar(`/remote.php/dav/calendars/${user}/${name}/`);
}
throw e;
} Prevention
- Throttle calendar creation client-side to the configured rateLimitCalendarCreation / rateLimitPeriodCalendarCreation values
- Raise the limit via occ config:app:set dav rateLimitCalendarCreation on servers used for provisioning or CI
- Reuse existing calendars instead of delete-and-recreate cycles
When it happens
Trigger: Performing MKCALENDAR/MKCOL (any bind that creates a node) on a three-segment path calendars/<username>/<newname> more than 10 times within one hour as the same user; typical with migration/import scripts, provisioning loops, or CalDAV clients that delete-and-recreate calendars repeatedly.
Common situations: Bulk import or sync tools creating many calendars in a loop; automated e2e tests running against a real server with default limits; admins unaware of the rate limit seeing 429 responses in client logs after Nextcloud 27+ introduced the plugin.
Related errors
- Too many addressbook or calendar share requests
- Calendar limit reached
- Too many addressbooks created
- Setting ACL is not supported on this node
- Deleting an entry is not implemented
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/f5b8a4b5ca61bbe3.
Report an issue: GitHub.