nextcloud/server · error · Sabre\DAV\Exception\Forbidden
VCard object exceeds $cardSizeLimit bytes
Error message
VCard object exceeds $cardSizeLimit bytes
What it means
Sabre\DAV\Exception\Forbidden thrown by CardDavValidatePlugin::beforePut (apps/dav/lib/CardDAV/Validation/CardDavValidatePlugin.php:36). The DAV server enforces a per-vCard size ceiling on PUT, read from the request CONTENT_LENGTH header and compared against the app config value 'card_size_limit' (default 5242880 bytes = 5 MiB). Oversized cards are rejected before parsing.
Source
Thrown at apps/dav/lib/CardDAV/Validation/CardDavValidatePlugin.php:36
use Sabre\HTTP\ResponseInterface;
class CardDavValidatePlugin extends ServerPlugin {
public function __construct(
private IAppConfig $config,
) {
}
#[\Override]
public function initialize(Server $server): void {
$server->on('beforeMethod:PUT', [$this, 'beforePut']);
}
public function beforePut(RequestInterface $request, ResponseInterface $response): bool {
// evaluate if card size exceeds defined limit
$cardSizeLimit = $this->config->getValueInt(Application::APP_ID, 'card_size_limit', 5242880);
if ((int)$request->getRawServerValue('CONTENT_LENGTH') > $cardSizeLimit) {
throw new Forbidden("VCard object exceeds $cardSizeLimit bytes");
}
// all tests passed return true
return true;
}
}
View on GitHub (pinned to ecdeb153ff)
Solutions
- Shrink the payload - downscale/remove the embedded PHOTO or trim oversized fields, then re-PUT
- Check the current limit with occ config:app:get dav card_size_limit and raise it if your data legitimately needs more (occ config:app:set dav card_size_limit --value 10485760)
- If raising the limit, also check webserver/PHP upload limits (client_max_body_size, upload_max_filesize, post_max_size) so the request is not cut off earlier
Example fix
# before
occ config:app:get dav card_size_limit # 5242880 -> 5 MB cards rejected
# after (server side, when bigger cards are wanted)
occ config:app:set dav card_size_limit --value 10485760
// client side: strip the embedded photo before PUT
if (isset($vcard->PHOTO)) { unset($vcard->PHOTO); } Defensive patterns
Strategy: validation
Validate before calling
// client-side: check payload size before PUT
const MAX = 5 * 1024 * 1024; // keep in sync with dav card_size_limit
const card = vcard.toString();
if (Buffer.byteLength(card) > MAX) {
stripPhotoOrFail(vcard, MAX);
} Try / catch
try {
await client.putCard(card);
} catch (e) {
if (e.status === 403 && /exceeds \d+ bytes/.test(e.message)) {
await shrinkCard(vcard); // remove PHOTO / large fields, then retry once
}
} Prevention
- Downscale contact photos before embedding them in vcards
- Prefer PHOTO-URI over inline base64 photos when the client allows
- Keep the client limit in sync with occ config:app:get dav card_size_limit
When it happens
Trigger: PUT to a card resource (e.g. /remote.php/dav/addressbooks/users/<uid>/<book>/<card>.vcf) where Content-Length exceeds occ config:app:get dav card_size_limit (default 5 MiB). Typically cards carrying a base64 PHOTO or a huge NOTE field.
Common situations: Contacts with high-resolution photos synced from Android/iOS; vCard 3.0 with inline images (no CARD:PHOTO-URI); admins who lowered card_size_limit; migrations importing enriched contact data.
Related errors
- VEvent or VTodo object exceeds $eventSizeLimit bytes
- AddressBook limit reached
- Only authors are allowed to edit their comment.
- Calendar limit reached
- Read-only sharees cannot permanently delete trashbin entries
AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17).
Data as JSON: /api/errors/b2217343984442cf.
Report an issue: GitHub.