React-native-notifee: Error in createTriggerNotification

Created on 29 Aug 2020  路  17Comments  路  Source: notifee/react-native-notifee

Hi,

While creating a createTriggerNotification I am getting error Data cannot occupy more than 10240 bytes when serialized. Using version 0.11.1

Android bug under-review

Most helpful comment

This is a change to be made in the underlying library (not the open source adapter here) - just wanted to leave a note that it is in progress. It is a non-trivial change, but there is already a non-trivial amount of work done on it. I won't promise to update all the time but I wanted to at least publicize that it is under development already

All 17 comments

Hi there @ashokkumar88! Could paste in the complete stack trace on this one? Plus a paste in of the code in your app that is triggering the problem?

My guess is that you are attempting to send serialized image data for your notification into the trigger, when you should send a reference or similar and fetch the data by reference? That guess is based on this: https://stackoverflow.com/questions/59134445/java-lang-illegalstateexception-data-cannot-occupy-more-than-10240-bytes-when-s

It is possible the module itself is doing it (which would be an error) or that successful usage patterns could be documented or clearly, or that inputs could be checked with more helpful error messages - but any change like that will depend on what we hear back from you

Hi, Thanks for your reply. For the smallIcon I am using the image from the android resource folder. And for the largeIcon I am using a remote image url. Also I tried without smallIcon and largeIcon. But still the error coming. Below is the code which triggering notification and stack trace.

const trigger = {
                type: TriggerType.TIME,
                timestamp:time,
                repeatInterval: 1,
                repeatIntervalTimeUnit: TimeUnit.DAYS
              };

const notificationData = {
                title:title,
                body:body,
                sound:self.sound,
                id: notificationId + id,
                data: {
                                      goalduration:"2", 
                                      goalid: "2",
                                      repeatTime: "1598880600000"
                                      type: "start"
                                      user_id: "1"
                                      username: "Ashok"},
                android:{
                    sound:self.sound,
                    channelId:'default-channel',
                    smallIcon:'ic_stat_onesignal_default',
                    largeIcon: LARGE_ICON_FROM_REMOTE_URL,
                    style: {type: AndroidStyle.BIGTEXT,text:body},
                    autoCancel: true,
                    importance: AndroidImportance.HIGH,
                    actions:actions,
                    pressAction: {
                        id: 'default',
                        launchActivity: 'default',
                        launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
                      },
                }
            }

            notifee.createTriggerNotification(notificationData,trigger)

And Below is the Stack Trace:

java.lang.IllegalStateException: Data cannot occupy more than 10240 bytes when serialized
        at androidx.work.Data.toByteArrayInternal(Data.java:417)
        at androidx.work.Data$Builder.build(Data.java:846)
        at n.o.t.i.f.e.e.nz_f.nz_n(SourceFile:317)
        at n.o.t.i.f.e.e.-$$Lambda$zSLbbWx0VUzGqCjcLRvAX335Aok.call(Unknown Source:4)
        at com.google.android.gms.tasks.zzy.run(com.google.android.gms:play-services-tasks@@17.1.0:2)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)

What is this?

              largeIcon: LARGE_ICON_FROM_REMOTE_URL,

Is it binary data stuffed in to a string?

No, It is a plain image url from server. Like this https://www.examaple.com/icon.png. Also I had tried without the largeIcon and smallIcon. But still it is throwing error.

Excellent - thanks for providing all the extra information, we'll investigate and that extra information is exactly what we need

Out of curiosity, this:

              style: {type: AndroidStyle.BIGTEXT,text:body},

...what would this resolve to? what are the contents of AndroidStyle.BIGTEXT after bundle generation etc - just curious of the style contents are large enough to cause a problem

Finally, I see this also:

              actions:actions,

Those are potentially unbounded and we may not be handling them. Can you specify the contents of 'actions' there? Stated another way - we need to see all of the code that is constructing this notification, including variable definitions so we can have a full reproduction

I do see something potentially problematic specifically around the large icon handling, in the Notifee core library source. If my hypothesis is correct, my expectation is that if you remove all large icon handling (don't send it, don't receive it, etc) and cleanly re-build to make sure that large icon is not passed through, it should not error this way.

But you mention specifically that you tested that - removing large icon - and it still had an error? That is surprising.

Can you triple-check that if you remove large icon you still see this problem? And if so, then one by one taking out small icon and style and actions and large icon - something in those attributes is too large compared with the way the current library is written, and causing it

@Salakar / @helenaford there appears to be a design issue with how user-supplied data is passed in to the Android APIs, if WorkManager is going to limit attached data to 10k

This code is present for both trigger styles:


    String uniqueWorkName = "trigger:" + notificationModel.getId();
    WorkManager workManager = WorkManager.getInstance(ContextHolder.getApplicationContext());

    long delay = trigger.getDelay();

    Data.Builder workDataBuilder =
        new Data.Builder()
            .putString(Worker.KEY_WORK_TYPE, Worker.WORK_TYPE_NOTIFICATION_TRIGGER)
            .putByteArray("trigger", ObjectUtils.bundleToBytes(triggerBundle))
            .putByteArray("notification", ObjectUtils.bundleToBytes(notificationModel.toBundle()));

    // One time trigger
    OneTimeWorkRequest.Builder workRequestBuilder = new OneTimeWorkRequest.Builder(Worker.class);
    workRequestBuilder.addTag(Worker.WORK_TYPE_NOTIFICATION_TRIGGER);
    workRequestBuilder.addTag(uniqueWorkName);
    workRequestBuilder.setInputData(workDataBuilder.build());

In particular, if my analysis is correct, rendering the triggerBundle and notificationModel to a byte array will always be liable to overflow, since they are constructed from potentially unbounded input (in the form of potentially unbounded small and large icon URLs, styles, and action sets).

In an unrelated project I dehydrate/persist items like that to cache files and set references into the Android message-passing data structures then re-hydrate from the cache files as needed

Sorry @ashokkumar88 for lots of messages but I'm just concluding my analysis here as I think you've found a deep issue. But you mention you are on version 11.1, could you upgrade to the most recent release (12.1) to make sure we are tracking current source.

I believe you will still reproduce the problem, but the source numbers in your stack trace might be slightly different and those could aid us in fixing this

Thanks

Hi @mikehardy,

The AndroidStyle.BIGTEXT resolves to "Hi, Ashok, Get geared up. Your Meditation session will start in 10 minutes"

const actions = [
                {
                    title:'START NOW',
                    pressAction: {
                        id:'start'
                    }
                },
                {
                    title:'LATER',
                    pressAction: {
                    id: 'later'
                    }
                }
            ];

Actually my use case is to trigger a notification in future time and then daily interval at triggered time. So I m using the repeatInterval feature which is available in 0.11.1. It has been removed in the latest version 0.12.1. Still I will check by using the latest version if it is throwing any error or not.

Ah yes - the repeatInterval thing - I believe there was a way to combine things such that you would have the same functionality, but when I went to reference that issue comment it was you :sweat_smile: - so you are aware. I do not believe your issue will be resolved with 12.1, but it would verify at least. Thanks again for working with us, it's already being looked at closely internally here and we'll keep you posted.

Also I found that in the object passing to data parameter there is automatically getter and setter functions added. Is it increasing the bytes?

Capture

...perhaps, but the underlying problem is that user-supplied content (potentially unbounded) is passed to the WorkManager API, and no amount of constant-size trimming (removing those getter/setters or anything similar) will be sufficient to guard against a single piece of user data that is too large. So it needs a deeper fix and then any constant-size improvements will be irrelevant I think

Now I commented out multiple parameters to check if it is throwing error or not. And it is not throwing any error after removing some parameters. But without these params the notification is incomplete. The issue is not with any particular parameter. The issue is with the total object bytes. I have commented data,actions,style. Check the commented lines below:

const notificationData = {
                title:title,
                body:body,
                sound:self.sound,
                id:notificationId + id,
            //     data: {...notifData},
                android:{
                    sound:self.sound,
                    channelId:self.sound == 'meditation' ? 'meditation-customsound-channel' : 'meditation-default-channel',
                    smallIcon:'ic_stat_onesignal_default',
                    largeIcon:"https://www.djjs.org/images/app/sadhak.png",
                    //style:{type:AndroidStyle.BIGTEXT,text:body},      
                    autoCancel:true,
                    importance:AndroidImportance.HIGH,
                    //actions:actions,
                    pressAction: {
                        id: 'default',
                        launchActivity: 'default',
                        launchActivityFlags: [AndroidLaunchActivityFlag.SINGLE_TOP],
                      },
                }
            }

So it's need a fix from the native side. WorkManager has only 12kb limit. Not sure if it will work like this to compress the data with gzip before passing to WorkManager and decompress while retrieving.

The need to handle unbounded data from the user implies the need for an unbounded data passing solution, it is in the core library component yes - it needs a change internally and a new release before it can successfully meet the API contract regardless of input

This is a change to be made in the underlying library (not the open source adapter here) - just wanted to leave a note that it is in progress. It is a non-trivial change, but there is already a non-trivial amount of work done on it. I won't promise to update all the time but I wanted to at least publicize that it is under development already

Thanks for reporting the issue, fix has been released in v0.13.0. 馃憤

Was this page helpful?
0 / 5 - 0 ratings