<?xml version="1.0" encoding="UTF-8"?>        <rss version="2.0"
             xmlns:atom="http://www.w3.org/2005/Atom"
             xmlns:dc="http://purl.org/dc/elements/1.1/"
             xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
             xmlns:admin="http://webns.net/mvcb/"
             xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
             xmlns:content="http://purl.org/rss/1.0/modules/content/">
        <channel>
            <title>
									CardDAV PUT returns 500 (NPE in VCard.parseVCard) when PHOTO has no TYPE parameter — breaks macOS Contacts sync - Feedback for Zextras				            </title>
            <link>https://community.zextras.com/forum/feedback-for-zextras/carddav-put-returns-500-npe-in-vcard-parsevcard-when-photo-has-no-type-parameter-breaks-macos-contacts-sync/</link>
            <description>Zextras Community Discussion Board</description>
            <language>en-US</language>
            <lastBuildDate>Thu, 08 Oct 2026 10:37:02 +0000</lastBuildDate>
            <generator>wpForo</generator>
            <ttl>60</ttl>
							                    <item>
                        <title>CardDAV PUT returns 500 (NPE in VCard.parseVCard) when PHOTO has no TYPE parameter — breaks macOS Contacts sync</title>
                        <link>https://community.zextras.com/forum/feedback-for-zextras/carddav-put-returns-500-npe-in-vcard-parsevcard-when-photo-has-no-type-parameter-breaks-macos-contacts-sync/#post-12593</link>
                        <pubDate>Thu, 06 Aug 2026 15:49:50 +0000</pubDate>
                        <description><![CDATA[Environment: Carbonio CE 26.6.0 (carbonio-appserver 4.5.1, appserver-conf 4.27.13, Ubuntu 24.04). Client: macOS 26.5 Contacts (AddressBookCore removed link ).
Problem: A CardDAV PUT of a vC...]]></description>
                        <content:encoded><![CDATA[<p><strong>Environment:</strong><span> </span>Carbonio CE 26.6.0 (carbonio-appserver 4.5.1, appserver-conf 4.27.13, Ubuntu 24.04). Client: macOS 26.5 Contacts (<span class="inline-block rounded- outline-none hide-focus-ring ring-focus"><code data-epitaxy-inline-code="" data-epitaxy-file-ref="">AddressBookCore <span style="color:#aaa">removed link</span> </code></span>).</p>
<p><strong>Problem:</strong><span> </span>A CardDAV<span> </span><code data-epitaxy-inline-code="">PUT</code><span> </span>of a vCard whose<span> </span><code data-epitaxy-inline-code="">PHOTO</code><span> </span>property carries no<span> </span><code data-epitaxy-inline-code="">TYPE</code><span> </span>parameter fails with HTTP 500. Current macOS Contacts adds<span> </span><code data-epitaxy-inline-code="">TYPE=JPEG</code><span> </span>for JPEG photos but omits the parameter entirely for<span> </span><strong>PNG</strong><span> </span>photos. Per RFC 2426<span> </span><code data-epitaxy-inline-code="">TYPE</code><span> </span>is optional, so the vCard is valid — but the server rejects it.</p>
<p><strong>Impact is bigger than one contact.</strong><span> </span>The client never gets a success, so it retries the same<span> </span><code data-epitaxy-inline-code="">PUT</code><span> </span>every 30-60 minutes forever, and the failing upload aborts the sync session<span> </span><em>before</em><span> </span>the download step. The result is a mailbox that looks like "CardDAV is broken on macOS": new contacts created on other devices never reach the Mac. In our case the account had one contact with a PNG photo and the whole address book stopped syncing on macOS while iOS and Thunderbird worked fine. Recovering required removing and re-adding the account on the Mac, because the queued upload survives both editing the contact and toggling Contacts for the account.</p>
<p><strong>Reproduce:</strong><span> </span><code data-epitaxy-inline-code="">PUT</code><span> </span>to<span> </span><code data-epitaxy-inline-code="">/dav/&lt;user&gt;/Contacts/&lt;uid&gt;.vcf</code>:</p>
<div class="epitaxy-codeblock relative max-w-full w-fit">
<div class="relative">
<div class="epitaxy-diff rounded-r6 overflow-clip" data-code-text="BEGIN:VCARD
VERSION:3.0
N:Doe;John;;;
FN:John Doe
PHOTO;ENCODING=b:iVBORw0KGgoAAAANSUhEUgAA...   (PNG payload, no TYPE parameter)
END:VCARD">
<div data-content="">
<div data-line="1" data-line-type="context" data-line-index="0"><span>BEGIN:VCARD</span></div>
<div data-line="2" data-line-type="context" data-line-index="1"><span>VERSION:3.0</span></div>
<div data-line="3" data-line-type="context" data-line-index="2"><span>N:Doe;John;;;</span></div>
<div data-line="4" data-line-type="context" data-line-index="3"><span>FN:John Doe</span></div>
<div data-line="5" data-line-type="context" data-line-index="4"><span>PHOTO;ENCODING=b:iVBORw0KGgoAAAANSUhEUgAA... (PNG payload, no TYPE parameter)</span></div>
<div data-line="6" data-line-type="context" data-line-index="5"><span>END:VCARD</span></div>
</div>
</div>
<div> </div>
<div class="absolute right- flex gap- top-">→ HTTP 500. The same vCard with <code data-epitaxy-inline-code="">PHOTO;ENCODING=b;TYPE=JPEG:...</code> is accepted.</div>
</div>
</div>
<p><strong>Server log (mailbox.log):</strong></p>
<div class="epitaxy-codeblock relative max-w-full w-fit">
<div class="relative">
<div class="epitaxy-diff rounded-r6 overflow-clip" data-code-text="ERROR  dav - error handling method PUT.  Sending HTTP Error - StatusCode 500
java.lang.NullPointerException: Cannot invoke &quot;String.toUpperCase()&quot; because the return value
of &quot;com.zimbra.cs.service.formatter.VCard$VCardProperty.getParamValue(String)&quot; is null
	at com.zimbra.cs.service.formatter.VCard.parseVCard(VCard.java:340)
	at com.zimbra.cs.dav.resource.AddressObject.uploadToVCard(AddressObject.java:223)
	at com.zimbra.cs.dav.resource.AddressObject.create(AddressObject.java:250)
	at com.zimbra.cs.dav.resource.Collection.createVCard(Collection.java:180)
	at com.zimbra.cs.dav.resource.AddressbookCollection.createItem(AddressbookCollection.java:93)
	at com.zimbra.cs.dav.service.method.Put.handle(Put.java:38)">
<div data-content="">
<div data-line="1" data-line-type="context" data-line-index="0"><span>ERROR  dav - error handling method PUT. Sending HTTP Error - StatusCode 500</span></div>
<div data-line="2" data-line-type="context" data-line-index="1"><span>java.lang.NullPointerException: Cannot invoke "String.toUpperCase()" because the return value</span></div>
<div data-line="3" data-line-type="context" data-line-index="2"><span>of "com.zimbra.cs.service.formatter.VCard$VCardProperty.getParamValue(String)" is null</span></div>
<div data-line="4" data-line-type="context" data-line-index="3"><span> at com.zimbra.cs.service.formatter.VCard.parseVCard(VCard.java:340)</span></div>
<div data-line="5" data-line-type="context" data-line-index="4"><span> at com.zimbra.cs.dav.resource.AddressObject.uploadToVCard(AddressObject.java:223)</span></div>
<div data-line="6" data-line-type="context" data-line-index="5"><span> at com.zimbra.cs.dav.resource.AddressObject.create(AddressObject.java:250)</span></div>
<div data-line="7" data-line-type="context" data-line-index="6"><span> at com.zimbra.cs.dav.resource.Collection.createVCard(Collection.java:180)</span></div>
<div data-line="8" data-line-type="context" data-line-index="7"><span> at com.zimbra.cs.dav.resource.AddressbookCollection.createItem(AddressbookCollection.java:93)</span></div>
<div data-line="9" data-line-type="context" data-line-index="8"><span> at com.zimbra.cs.dav.service.method.Put.handle(Put.java:38)</span></div>
</div>
</div>
<div class="absolute right- flex gap- top-"> </div>
</div>
</div>
<p><strong>Cause and suggested fix</strong><span> </span>—<span> </span><code data-epitaxy-inline-code="">VCard.java</code><span> </span>line 340 calls<span> </span><code data-epitaxy-inline-code="">.toUpperCase()</code><span> </span>on a value that is<span> </span><code data-epitaxy-inline-code="">null</code><span> </span>when the parameter is absent. The very next lines already handle an empty suffix, so the guard looks like an oversight:</p>
<div class="epitaxy-codeblock relative max-w-full w-fit">
<div class="relative">
<div class="epitaxy-diff rounded-r6 overflow-clip" data-code-text="String typeParam = vcprop.getParamValue(&quot;TYPE&quot;);
String suffix = typeParam != null ? typeParam.toUpperCase() : &quot;&quot;;">
<div data-content="">
<div data-line="1" data-line-type="context" data-line-index="0"><span>String</span><span> typeParam </span><span>=</span><span> vcprop</span><span>.</span><span>getParamValue</span><span>(</span><span>"TYPE"</span><span>);</span></div>
<div data-line="2" data-line-type="context" data-line-index="1"><span>String</span><span> suffix </span><span>=</span><span> typeParam </span><span>!=</span><span> null</span><span> ?</span><span> typeParam</span><span>.</span><span>toUpperCase</span><span>()</span><span> :</span><span> ""</span><span>;</span></div>
</div>
</div>
<div class="absolute right- flex gap- top-"> </div>
</div>
</div>
<p>If a concrete subtype is needed, it can be detected from the decoded payload's magic bytes (<code data-epitaxy-inline-code="">\x89PNG</code>,<span> </span><code data-epitaxy-inline-code="">\xFF\xD8\xFF</code><span> </span>for JPEG).</p>
<p>I originally filed this on GitHub as<span> </span>&lt;a id=&quot;base-ui-_r_2tjm_&quot; class=&quot;text-accent hover:underline underline-offset- outline-none hide-focus-ring ring-focus rounded-r2&quot; href=&quot; <span style="color:#aaa">removed link</span> " target="_blank" rel="noopener noreferrer"&gt;zextras/carbonio-mailbox#1117</a><span> </span>and it was closed automatically with a pointer to this forum, so I am reposting it here.</p>]]></content:encoded>
						                            <category domain="https://community.zextras.com/forum/feedback-for-zextras/">Feedback for Zextras</category>                        <dc:creator>soniqsofteu</dc:creator>
                        <guid isPermaLink="true">https://community.zextras.com/forum/feedback-for-zextras/carddav-put-returns-500-npe-in-vcard-parsevcard-when-photo-has-no-type-parameter-breaks-macos-contacts-sync/#post-12593</guid>
                    </item>
							        </channel>
        </rss>
		