Contacts import aborts with TypeError when vCards have no UID (TextImporter structure)

Offen Anfängerfreundlich
#66,486 2 Kommentare 2 Reaktionen 1 zugewiesene Person Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

@SebastianKrupinski arbeitet bereits daran.

Seit 10.11.2026.

  • #66489 von @lazerg — offen
  • #66512 von @SebastianKrupinski — offen

Bewertung

Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
72/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
php
Bereich
backend

Rechercherichtung

Beginne in apps/dav/lib/CardDAV/Import/TextImporter.php, in analyze(), wo Komponenten ohne UID als bloße Instanzen statt als Listen gespeichert werden. Prüfe dann ImportService::importText() um Zeile 75, das $instances[0] liest. Die Korrektur besteht darin, den Eintrag ohne UID in eine Liste zu packen, und dasselbe Muster muss in apps/dav/lib/CalDAV/Import/TextImporter.php geprüft werden. Erledigt, wenn eine vCard ohne UID erfolgreich importiert wird, verifiziert mit einem Test in den apps/dav-Importtests.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

bug
Bug description

Importing a .vcf file in the Contacts app ("Import contacts") fails completely ("0 of 629 imported") when the vCards have no UID property. A Google Contacts export is the typical case: none of its 629 cards had a UID.

The server log shows:

TypeError: OCA\DAV\CardDAV\Import\TextImporter::extract(): Argument #1 ($start) must be of type int, string given,
called in apps/dav/lib/CardDAV/Import/ImportService.php on line 75

(request: /ocs/v2.php/contacts/import)

Cause

In apps/dav/lib/CardDAV/Import/TextImporter.php::analyze(), a component with a UID is stored as a list of instances:

$this->structure[$componentType][$componentId][] = [$componentType, $componentId, $componentStart, $componentEnd];

A component without a UID is stored as a bare instance, not wrapped in a list:

$this->structure[$componentType][] = [$componentType, $componentId, $componentStart, $componentEnd];

ImportService::importText() expects a list of instances in both cases:

foreach ($structure['VCARD'] as $cid => $instances) {
    $instance = $instances[0];                                   // "VCARD" (string) for UID-less cards
    $sObjectContents = $importer->extract($instance[2], $instance[3]);  // "A", "R" -> TypeError

The generator throws on the first UID-less card, so the whole import is aborted.

The same pattern exists in apps/dav/lib/CalDAV/Import/TextImporter.php. There, ImportService casts the values with (int), so it does not throw, but it would read wrong byte ranges.

Steps to reproduce
  1. Create test.vcf:
    BEGIN:VCARD
    VERSION:3.0
    FN:Erika Mustermann
    N:Mustermann;Erika;;;
    TEL;TYPE=CELL:+49 170 0000000
    END:VCARD
    
  2. Contacts → Contacts settings → Import contacts → choose test.vcf.
  3. Result: "0 of 1 imported", with the TypeError above in nextcloud.log.

Adding a UID: line to each card makes the import succeed. I verified this with the original file: all 629 cards imported.

Expected behavior

vCards without a UID are imported. A UID is optional in vCard 3.0, and the CardDAV backend can generate one.

Suggested fix

Wrap the UID-less entry in a list as well, for example:

$this->structure[$componentType][] = [[$componentType, $componentId, $componentStart, $componentEnd]];

The same applies to the CalDAV TextImporter.

Versions
  • Nextcloud 35.0.2 (Docker image nextcloud:35-apache), PHP 8.5.12, MariaDB 11.4
  • Contacts app 8.9.5
  • The same code is in master, stable35 and stable34 as of today.
Vorherrschende Sprache
PHP
Sterne
37.5k
Forks
5.4k
Ø Merge
1 T. 14 Std.
Gemergte PRs (30 T.)
648

Entwicklungsumgebung

In Codespaces öffnen

Startet den Dev-Container des Projekts im Browser, mit Ihrem eigenen GitHub-Konto.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus nextcloud/server

Alle Issues in nextcloud/server

Ähnliche Issues

Weitere Issues zu PHP

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.