{"record":{"id":"77edcafdb662b637","repo":"nextcloud/server","slug":"too-many-addressbooks-created","errorCode":null,"errorMessage":"Too many addressbooks created","messagePattern":"Too many addressbooks created","errorType":"http","errorClass":"OCA\\DAV\\Connector\\Sabre\\Exception\\TooManyRequests","httpStatus":429,"severity":"warning","filePath":"apps/dav/lib/CardDAV/Security/CardDavRateLimitingPlugin.php","lineNumber":68,"sourceCode":"\t\t}\n\t\t$user = $this->userManager->get($this->userId);\n\t\tif ($user === null) {\n\t\t\t// We only care about authenticated users here\n\t\t\treturn;\n\t\t}\n\n\t\t$pathParts = explode('/', $path);\n\t\tif (count($pathParts) === 4 && $pathParts[0] === 'addressbooks') {\n\t\t\t// Path looks like addressbooks/users/username/addressbooksname so a new addressbook is created\n\t\t\ttry {\n\t\t\t\t$this->limiter->registerUserRequest(\n\t\t\t\t\t'carddav-create-address-book',\n\t\t\t\t\t$this->config->getValueInt('dav', 'rateLimitAddressBookCreation', 10),\n\t\t\t\t\t$this->config->getValueInt('dav', 'rateLimitPeriodAddressBookCreation', 3600),\n\t\t\t\t\t$user\n\t\t\t\t);\n\t\t\t} catch (RateLimitExceededException $e) {\n\t\t\t\tthrow new TooManyRequests('Too many addressbooks created', 0, $e);\n\t\t\t}\n\n\t\t\t$addressBookLimit = $this->config->getValueInt('dav', 'maximumAdressbooks', 10);\n\t\t\tif ($addressBookLimit === -1) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t$numAddressbooks = $this->cardDavBackend->getAddressBooksForUserCount('principals/users/' . $user->getUID());\n\n\t\t\tif ($numAddressbooks >= $addressBookLimit) {\n\t\t\t\t$this->logger->warning('Maximum number of address books reached', [\n\t\t\t\t\t'addressbooks' => $numAddressbooks,\n\t\t\t\t\t'addressBookLimit' => $addressBookLimit,\n\t\t\t\t]);\n\t\t\t\tthrow new Forbidden('AddressBook limit reached', 0);\n\t\t\t}\n\t\t}\n\t}\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/dav/lib/CardDAV/Security/CardDavRateLimitingPlugin.php#L50-L86","documentation":"CardDavRateLimitingPlugin counts MKCOL requests that create addressbooks (paths of exactly four segments starting with addressbooks/) per user in the app rate limiter: action 'carddav-create-address-book', budget dav rateLimitAddressBookCreation (default 10) per dav rateLimitPeriodAddressBookCreation seconds (default 3600). Exceeding the budget throws TooManyRequests (HTTP 429).","triggerScenarios":"More than 10 MKCOL addressbook creations by the same user within one hour (defaults); provisioning scripts or test suites bulk-creating books; a sync client stuck recreating books in a loop.","commonSituations":"Automated onboarding creating one addressbook per team; CI running against a single test user; failed creations being retried immediately (each attempt still consumes budget).","solutions":["Honor the 429: wait out the window (default 1 hour) or slow the creation rate","Raise the budget: occ config:app:set dav rateLimitAddressBookCreation --value='100' and occ config:app:set dav rateLimitPeriodAddressBookCreation --value='3600'","Fix the loop causing mass creation attempts - failed MKCOLs count too","Spread automated creations across users or time"],"exampleFix":"# before\nfor i in $(seq 1 50): MKCOL /addressbooks/users/alice/book-$i/\n-> 429 Too many addressbooks created\n\n# after\nocc config:app:set dav rateLimitAddressBookCreation --value='100'\nfor i in $(seq 1 50): MKCOL /addressbooks/users/alice/book-$i/  -> 201","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    $client->request('MKCOL', $uri);\n} catch (\\Sabre\\HTTP\\ClientHttpException $e) {\n    if ($e->getResponse()->getStatus() === 429) {\n        $wait = (int) ($e->getResponse()->getHeader('Retry-After')[0] ?? 3600);\n        sleep(min($wait, 3600));\n        $client->request('MKCOL', $uri); // single retry after the window\n    }\n}","preventionTips":["Throttle addressbook creation client-side (default budget: 10 per hour per user)","Honor 429 responses and remember the knobs: dav rateLimitAddressBookCreation and rateLimitPeriodAddressBookCreation","Fix creation-retry loops - failed MKCOLs still consume rate-limit budget"],"tags":["carddav","dav","rate-limit","http-429","mkcol"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}