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

Aperta Adatta ai principianti
#66,486 2 commenti 2 reazioni 1 assegnatario Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@SebastianKrupinski ci sta già lavorando.

Dal 10/11/2026.

  • #66489 di @lazerg — aperta
  • #66512 di @SebastianKrupinski — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
php
Ambito
backend

Direzione di ricerca

Inizia in apps/dav/lib/CardDAV/Import/TextImporter.php, in analyze(), dove i componenti senza UID vengono memorizzati come semplici istanze invece che come liste. Poi controlla ImportService::importText() intorno alla riga 75, che legge $instances[0]. La correzione consiste nell’avvolgere la voce senza UID in una lista, e lo stesso schema va controllato in apps/dav/lib/CalDAV/Import/TextImporter.php. Fatto quando una vCard senza UID viene importata correttamente, verificato con un test nei test di importazione di apps/dav.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.
Lingua principale
PHP
Stelle
37.5k
Fork
5.4k
Merge medio
1g 14h
PR unite (30g)
648

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di nextcloud/server

Tutte le issue di nextcloud/server

Issue simili

Altre issue su PHP

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.