android icon indicating copy to clipboard operation
android copied to clipboard

Calendar sync failed: Error while applying remote entries

Open intentionally-left-nil opened this issue 4 years ago • 2 comments

I have the syncbase app on my mac desktop, as well as the client on android. What I think happened is I accepted a cal invite on my desktop, and now it has caused this exception on android every time it tries to sync:

I'm not sure exactly which invite is causing this, but please let me know if there's more information I can gather.

2021-04-19 09:52:56 1003 [ICalendar] Parsing iCalendar stream
2021-04-19 09:52:56 1003 Unfolding...
2021-04-19 09:52:56 1003 Unfolding...
2021-04-19 09:52:56 1003 [com.etesync.syncadapter.syncadapter.SyncNotification] Unknown sync error
EXCEPTION at.bitfire.ical4android.InvalidCalendarException: Couldn't parse iCalendar
	at at.bitfire.ical4android.ICalendar$Companion.fromReader(ICalendar.kt:84)
	at at.bitfire.ical4android.Event$Companion.eventsFromReader(Event.kt:85)
	at at.bitfire.ical4android.Event$Companion.eventsFromReader$default(Event.kt:84)
	at com.etesync.syncadapter.syncadapter.CalendarSyncManager.processItem(CalendarSyncManager.kt:89)
	at com.etesync.syncadapter.syncadapter.SyncManager.applyRemoteItems(SyncManager.kt:470)
	at com.etesync.syncadapter.syncadapter.SyncManager.performSync(SyncManager.kt:252)
	at com.etesync.syncadapter.syncadapter.CalendarsSyncAdapterService$SyncAdapter.onPerformSyncDo(CalendarsSyncAdapterService.kt:50)
	at com.etesync.syncadapter.syncadapter.SyncAdapterService$SyncAdapter.onPerformSync(SyncAdapterService.kt:117)
	at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:334)
Caused by: net.fortuna.ical4j.data.ParserException: Error at line 15:String index out of range: -1
	at net.fortuna.ical4j.data.CalendarParserImpl.parse(CalendarParserImpl.java:160)
	at net.fortuna.ical4j.data.CalendarBuilder.build(CalendarBuilder.java:183)
	at net.fortuna.ical4j.data.CalendarBuilder.build(CalendarBuilder.java:171)
	at at.bitfire.ical4android.ICalendar$Companion.fromReader(ICalendar.kt:82)
	... 8 more
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1
	at java.lang.String.substring(String.java:2064)
	at net.fortuna.ical4j.model.property.Geo.setValue(Geo.java:209)
	at net.fortuna.ical4j.model.property.Geo.<init>(Geo.java:166)
	at net.fortuna.ical4j.model.property.Geo$Factory.createProperty(Geo.java:255)
	at net.fortuna.ical4j.model.PropertyBuilder.build(PropertyBuilder.java:48)
	at net.fortuna.ical4j.data.DefaultContentHandler.endProperty(DefaultContentHandler.java:123)
	at net.fortuna.ical4j.data.CalendarParserImpl$PropertyParser.parse(CalendarParserImpl.java:294)
	at net.fortuna.ical4j.data.CalendarParserImpl$PropertyParser.access$1100(CalendarParserImpl.java:226)
	at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:213)
	at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.parse(CalendarParserImpl.java:429)
	at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.access$900(CalendarParserImpl.java:406)
	at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:211)
	at net.fortuna.ical4j.data.CalendarParserImpl.parseCalendar(CalendarParserImpl.java:116)
	at net.fortuna.ical4j.data.CalendarParserImpl.parseCalendarList(CalendarParserImpl.java:182)
	at net.fortuna.ical4j.data.CalendarParserImpl.parse(CalendarParserImpl.java:151)
	... 11 more

2021-04-19 09:52:56 1003 [com.etesync.syncadapter.syncadapter.CalendarsSyncAdapterService] Calendar sync complete
2021-04-19 09:52:56 898 [com.etesync.syncadapter.AccountSettings] Account <myaccount> has version 2, current version: 2

intentionally-left-nil avatar Apr 19 '21 16:04 intentionally-left-nil

Same issue here, but on Android with the EteSync client:

--- BEGIN DEBUG INFO --- SYNCHRONIZATION INFO Synchronization phase: applying remote entries Account name: withheld Authority: com.android.calendar Debug activity source: class com.etesync.syncadapter.syncadapter.SyncNotification$NotificationHandlerActivity (Kotlin reflection is not available)

EXCEPTION: at.bitfire.ical4android.InvalidCalendarException: Couldn't parse iCalendar at at.bitfire.ical4android.ICalendar$Companion.fromReader(ICalendar.kt:84) at at.bitfire.ical4android.Event$Companion.eventsFromReader(Event.kt:85) at at.bitfire.ical4android.Event$Companion.eventsFromReader$default(Event.kt:84) at com.etesync.syncadapter.syncadapter.CalendarSyncManager.processItem(CalendarSyncManager.kt:89) at com.etesync.syncadapter.syncadapter.SyncManager.applyRemoteItems(SyncManager.kt:470) at com.etesync.syncadapter.syncadapter.SyncManager.performSync(SyncManager.kt:252) at com.etesync.syncadapter.syncadapter.CalendarsSyncAdapterService$SyncAdapter.onPerformSyncDo(CalendarsSyncAdapterService.kt:50) at com.etesync.syncadapter.syncadapter.SyncAdapterService$SyncAdapter.onPerformSync(SyncAdapterService.kt:117) at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:334) Caused by: net.fortuna.ical4j.data.ParserException: Error at line 15:Text cannot be parsed to a Duration at net.fortuna.ical4j.data.CalendarParserImpl.parse(CalendarParserImpl.java:160) at net.fortuna.ical4j.data.CalendarBuilder.build(CalendarBuilder.java:183) at net.fortuna.ical4j.data.CalendarBuilder.build(CalendarBuilder.java:171) at at.bitfire.ical4android.ICalendar$Companion.fromReader(ICalendar.kt:82) ... 8 more Caused by: j$.time.format.x: Text cannot be parsed to a Duration at j$.time.Duration.parse(:412) at net.fortuna.ical4j.model.TemporalAmountAdapter.parse(TemporalAmountAdapter.java:137) at net.fortuna.ical4j.model.property.Trigger.setValue(Trigger.java:270) at net.fortuna.ical4j.model.property.Trigger.(Trigger.java:165) at net.fortuna.ical4j.model.property.Trigger$Factory.createProperty(Trigger.java:315) at net.fortuna.ical4j.model.PropertyBuilder.build(PropertyBuilder.java:48) at net.fortuna.ical4j.data.DefaultContentHandler.endProperty(DefaultContentHandler.java:123) at net.fortuna.ical4j.data.CalendarParserImpl$PropertyParser.parse(CalendarParserImpl.java:294) at net.fortuna.ical4j.data.CalendarParserImpl$PropertyParser.access$1100(CalendarParserImpl.java:226) at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:213) at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.parse(CalendarParserImpl.java:429) at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.access$900(CalendarParserImpl.java:406) at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:211) at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.parse(CalendarParserImpl.java:429) at net.fortuna.ical4j.data.CalendarParserImpl$ComponentParser.access$900(CalendarParserImpl.java:406) at net.fortuna.ical4j.data.CalendarParserImpl$PropertyListParser.parse(CalendarParserImpl.java:211) at net.fortuna.ical4j.data.CalendarParserImpl.parseCalendar(CalendarParserImpl.java:116) at net.fortuna.ical4j.data.CalendarParserImpl.parseCalendarList(CalendarParserImpl.java:182) at net.fortuna.ical4j.data.CalendarParserImpl.parse(CalendarParserImpl.java:151) ... 11 more

SOFTWARE INFORMATION EteSync version: 2.2.4 (20204) Installed from: com.google.android.packageinstaller CONFIGURATION Power saving disabled: yes android.permission.READ_CONTACTS permission: granted android.permission.WRITE_CONTACTS permission: granted android.permission.READ_CALENDAR permission: granted android.permission.WRITE_CALENDAR permission: granted org.dmfs.permission.READ_TASKS permission: denied org.dmfs.permission.WRITE_TASKS permission: denied org.tasks.permission.READ_TASKS permission: granted org.tasks.permission.WRITE_TASKS permission: granted System-wide synchronization: automatically Account: withheld Address book sync. interval: manually Calendar sync. interval: manually OpenTasks sync. interval: — Tasks.org sync. interval: manually WiFi only: false [CardDAV] Contact group method: GROUP_VCARDS Manage calendar colors: true Address book account: Contacts ( withheld L8) Main account: Account {name= withheld, type=com.etesync.syncadapter} URL: L8ZTDx4UFQi_np9YWKaHj0t-PAzmyjXu Sync automatically: true

SQLITE DUMP android_metadata | locale | | en_US |

settings | setting | value |

SERVICES DUMP

JOURNALS DUMP

SYSTEM INFORMATION Android version: 9 (PPS29.118-15-11-16) Device: Motorola moto g(6) (ali)

--- END DEBUG INFO ---

shawn1thompson avatar Jun 14 '21 22:06 shawn1thompson

Okay, I was finally able to get a debug version installed and finished debugging.

In my case, the issue was that I had an iCal entry that contained this invalid field: GEO: (missing the coordinates and therefore not valid according to the spec: https://www.kanzaki.com/docs/ical/geo.html)

So what's going on here appears to be different parsing rules depending on the application. I believe this calendar was first imported into etesync via the MacOS calendar app. It must have succeeded the initial validation. However, when trying to sync the calendar app to the android client, the ical4j library doesn't like the entry, and throws an exception. This is especially problematic because it stops further processing and no more calendar entries are updated as long as a single calendar has a parsing issue.

I propose two fixes to this problem:

Easy workaround: Catch parsing exceptions and continue applying the remaining items. In its simplest, this just involves adding something similar to this try/catch:

private fun applyRemoteItems(itemList: ItemListResponse) {
        val items = itemList.data
        // Process new vcards from server
        val size = items.size
        var i = 0

        for (item in items) {
            if (Thread.interrupted()) {
                throw InterruptedException()
            }
            i++
            Logger.log.info("Processing (${i}/${size}) UID=${item.uid} Etag=${item.etag}")

            try {
                processItem(item)
                persistItem(item)
            } catch (e: InvalidCalendarException) {
                Logger.log.warning("iCal item (${i}/${size}) was invalid and could not be parsed. UID=${item.uid} Etag=${item.etag}")
            }
        }
    }

in syncmanager.kt

Pros: Easy fix, Reduction of severity - one bad cal entry doesn't prevent syncing the remaining cal entries Cons: Users aren't notified that some of their cal entries didn't sync because of a parsing bug

IMO a better, but more involved solution would be to notify the user that the remote cal entry has a bug, and offer to delete (or re-create) the cal entry.

intentionally-left-nil avatar Mar 12 '22 07:03 intentionally-left-nil