Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Installation fails to save: SQLiteConstraintException #266

Closed
alexblack opened this issue Nov 24, 2015 · 18 comments
Closed

Installation fails to save: SQLiteConstraintException #266

alexblack opened this issue Nov 24, 2015 · 18 comments

Comments

@alexblack
Copy link

Non-fatal Exception: java.lang.Exception: bolts.AggregateException: There were 2 exceptions.
       at com.aadhk.woinvoice.util.ParseInit$2.then(ProGuard:195)
       at com.aadhk.woinvoice.util.ParseInit$2.then(ProGuard:173)
       at bolts.Task$15.run(ProGuard:839)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:818)
Caused by bolts.AggregateException: There were 2 exceptions.
       at bolts.Task$8.then(ProGuard:483)
       at bolts.Task$8.then(ProGuard:465)
       at bolts.Task$14.run(ProGuard:798)
       at bolts.BoltsExecutors$ImmediateExecutor.execute(ProGuard:105)
       at bolts.Task.completeImmediately(ProGuard:789)
       at bolts.Task.access$000(ProGuard:32)
       at bolts.Task$10.then(ProGuard:581)
       at bolts.Task$10.then(ProGuard:578)
       at bolts.Task.runContinuations(ProGuard:875)
       at bolts.Task.trySetError(ProGuard:929)
       at bolts.TaskCompletionSource.trySetError(ProGuard:46)
       at bolts.TaskCompletionSource.setError(ProGuard:71)
       at bolts.Task$15$1.then(ProGuard:854)
       at bolts.Task$15$1.then(ProGuard:843)
       at bolts.Task$14.run(ProGuard:798)
       at bolts.BoltsExecutors$ImmediateExecutor.execute(ProGuard:105)
       at bolts.Task.completeImmediately(ProGuard:789)
       at bolts.Task.access$000(ProGuard:32)
       at bolts.Task$10.then(ProGuard:581)
       at bolts.Task$10.then(ProGuard:578)
       at bolts.Task.runContinuations(ProGuard:875)
       at bolts.Task.trySetError(ProGuard:929)
       at bolts.TaskCompletionSource.trySetError(ProGuard:46)
       at bolts.TaskCompletionSource.setError(ProGuard:71)
       at bolts.Task$15$1.then(ProGuard:854)
       at bolts.Task$15$1.then(ProGuard:843)
       at bolts.Task$14.run(ProGuard:798)
       at bolts.BoltsExecutors$ImmediateExecutor.execute(ProGuard:105)
       at bolts.Task.completeImmediately(ProGuard:789)
       at bolts.Task.access$000(ProGuard:32)
       at bolts.Task$10.then(ProGuard:581)
       at bolts.Task$10.then(ProGuard:578)
       at bolts.Task.runContinuations(ProGuard:875)
       at bolts.Task.trySetError(ProGuard:929)
       at bolts.TaskCompletionSource.trySetError(ProGuard:46)
       at bolts.TaskCompletionSource.setError(ProGuard:71)
       at bolts.Task$15$1.then(ProGuard:854)
       at bolts.Task$15$1.then(ProGuard:843)
       at bolts.Task$14.run(ProGuard:798)
       at bolts.BoltsExecutors$ImmediateExecutor.execute(ProGuard:105)
       at bolts.Task.completeImmediately(ProGuard:789)
       at bolts.Task.continueWith(ProGuard:588)
       at bolts.Task.continueWith(ProGuard:599)
       at bolts.Task$15.run(ProGuard:843)
       at bolts.BoltsExecutors$ImmediateExecutor.execute(ProGuard:105)
       at bolts.Task.completeAfterTask(ProGuard:830)
       at bolts.Task.access$100(ProGuard:32)
       at bolts.Task$11.then(ProGuard:635)
       at bolts.Task$11.then(ProGuard:632)
       at bolts.Task.runContinuations(ProGuard:875)
       at bolts.Task.trySetError(ProGuard:929)
       at bolts.TaskCompletionSource.trySetError(ProGuard:46)
       at bolts.TaskCompletionSource.setError(ProGuard:71)
       at bolts.Task$15$1.then(ProGuard:854)
       at bolts.Task$15$1.then(ProGuard:843)
       at bolts.Task$14.run(ProGuard:798)
       at bolts.BoltsExecutors$ImmediateExecutor.execute(ProGuard:105)
       at bolts.Task.completeImmediately(ProGuard:789)
       at bolts.Task.continueWith(ProGuard:588)
       at bolts.Task.continueWith(ProGuard:599)
       at bolts.Task$15.run(ProGuard:843)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:818)
Caused by android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: ParseObjects.className, ParseObjects.objectId (code 2067)
       at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(SQLiteConnection.java)
       at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:904)
       at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
       at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
       at android.database.sqlite.SQLiteDatabase.updateWithOnConflict(SQLiteDatabase.java:1697)
       at android.database.sqlite.SQLiteDatabase.update(SQLiteDatabase.java:1643)
       at com.parse.ParseSQLiteDatabase$22.then(ProGuard:317)
       at com.parse.ParseSQLiteDatabase$22.then(ProGuard:314)
       at bolts.Task$14.run(ProGuard:798)
       at bolts.BoltsExecutors$ImmediateExecutor.execute(ProGuard:105)
       at bolts.Task.completeImmediately(ProGuard:789)
       at bolts.Task.continueWith(ProGuard:588)
       at bolts.Task.continueWith(ProGuard:599)
       at bolts.Task$12.then(ProGuard:693)
       at bolts.Task$12.then(ProGuard:681)
       at bolts.Task$15.run(ProGuard:839)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:818)

This is happening when the installation is being saved. Here is the data I am capturing about the installation

msg There were 2 exceptions. 
createdat   Sun Apr 26 09:05:07 AEST 2015 
name    installation.save-failed 
appversion  0.1.181 
installationid  534a2cf7-4985-4645-91dc-15a4a7359eed 
idx 54 
devicetype  android 
objectid    l1gKEKIQJD 
runcount    306 
updatedat   Wed Nov 25 08:39:11 AEDT 2015 

Another:

msg There were 2 exceptions. 
createdat   Wed Aug 12 20:10:18 PDT 2015 
name    installation.save-failed 
appversion  0.1.181 
installationid  daf456d6-1b8f-4606-8e22-ba6357346392 
idx 115 
devicetype  android 
objectid    FQR2dDQhwW 
runcount    233 
updatedat   Tue Nov 24 14:53:03 PST 2015 

And another:

msg There were 2 exceptions. 
createdat   Thu Oct 22 15:41:45 CEST 2015 
name    installation.save-failed 
appversion  0.1.181 
installationid  c152d6b5-0e75-44b9-b74c-5ded448ff582 
idx 136 
devicetype  android 
objectid    b400fFV3BK 
runcount    25 
updatedat   Tue Nov 24 20:11:25 CET 2015 
@alexblack alexblack changed the title SQLiteConstraintException Installation fails to save: SQLiteConstraintException Nov 24, 2015
@parse-github-bot
Copy link

Thank you for your feedback. We prioritize issues that have clear and concise repro steps. Please see our Bug Reporting Guidelines about what information should be added to this issue.

Please try the latest SDK. Our release notes have details about what issues were fixed in each release.

In addition, you might find the following resources helpful:

@alexblack
Copy link
Author

HI @wangmengyan95 , similar to that other issue, I'm a bit stumped as to what would cause this, I am not familiar with the internals of parse and didn't expect to get a SQLException.

I've included data I captured from 3 users who encountered this, I'm happy to collect more data if you require.

Alex

@grantland
Copy link
Contributor

  • What version of the SDK is this?
  • What version of Bolts are you using?
  • There should be two exceptions from the AggregateException, could you post the other one?
  • Could you post the code from the stacktrace at the following lines?
       at com.aadhk.woinvoice.util.ParseInit$2.then(ProGuard:195)
       at com.aadhk.woinvoice.util.ParseInit$2.then(ProGuard:173)

@alexblack
Copy link
Author

SDK: 1.11.0
Bolts: 1.3.0
Other exception: I only have what is contained in the exception above, I can look at adding some code to log the 2 exceptions separately. I wonder if its: #267

Line 195:
App.err(ctx, "Failed to save parse installation", new Exception(task.getError()));
Line 173:
return installation.saveInBackground().continueWithTask(new Continuation<Void,

The whole file: http://pastebin.com/kM2izbX7

@grantland
Copy link
Contributor

Hrmm this looks like this is caused by your ParseInstallation save resulting in an objectId that your LDS is already tracking. The only way I could see this occurring right now is that there's a problem with fetching the current ParseInstallation (A) from LDS which causes a new ParseInstallation (A') instance to be created that has the same installationId as the one LDS is tracking. When the new ParseInstallation instance (A') gets saved, Parse de-duplicates the two instances (A and A') and returns success with the original instance's (A) objectId. The client then tries to update LDS with the save operation's result, which causes the unique constraint problem since a row already exists with that className and objectId.

Are you able to reproduce this and provide repro steps? We can't really change anything in the SDK to resolve this since we can't propagate why we can't read the current ParseInstallation initially due to backwards compatibility issues, but if you're able to reproduce it we can step through in debugging and find the cause of this.

WRT the AggregateException, it seems like there's an issue where logging a wrapped AggregateException (new Exception(aggregate)) it will lose the inner exception information. This will be tracked here:

@alexblack
Copy link
Author

I'm not able to repro this. If you have any insights on how to do that please let me know.

"We can't really change anything in the SDK to resolve this since we can't propagate why we can't read the current ParseInstallation"

I think a normal solution to this would be to have a non-breaking way to propagate why you can't read the current ParseInstallation.

Aggregate exception - nice!

@grantland
Copy link
Contributor

I think a normal solution to this would be to have a non-breaking way to propagate why you can't read the current ParseInstallation.

Yes this would be optimal, but it's not possible without breaking changes.

Unfortunately we cannot help in reproducing this since you and your developers are the only ones with a complete understanding of the scope of your app. In addition, without proper steps to reproduce this, we cannot proceed with this issue.

Please review our Contributing Guidelines for more information.

@alexblack
Copy link
Author

Sorry I'm not sure what you mean.. by definition a "non-breaking way" is non-breaking...?

@alexblack alexblack reopened this Dec 4, 2015
@alexblack
Copy link
Author

This issue is definitely possible to fix, and if you are willing to help I am confident we can get it fixed. Let me know. For example, I could modify your source code, and find a non-breaking way to propagate the actual error, then log it. If you're not willing to do that, I'd appreciate you mentioning why.

@grantland
Copy link
Contributor

Yes, you're asking for a non-breaking solution to propagate why we can't read from LDS. I'm saying that it would be optimal if this were possible, but it's not possible without breaking changes in our API.

I'm willing to help, but we need concise repro steps to do so as per our Contributing Guidelines.

@alexblack
Copy link
Author

You're contradicting yourself, a non-breaking solution can't be a breaking change :) Please elaborate.

@grantland
Copy link
Contributor

To reiterate: it would be great if there was a non-breaking solution, but there isn't.

@alexblack
Copy link
Author

That seems pretty unlikely :) If you were willing to help we could brainstorm a creative non-breaking way to get the information out.

I mean for starters, you could just log the problem to your server. Maybe there are reasons you don't want to do that, but that is just one of many possible non-breaking ways.

(Unless I'm misunderstanding something)

@grantland
Copy link
Contributor

To add on to my previous comment, it seems like this is happening due to a ParseInstallation instance being created when reading from LDS fails here because we use continueWith to swallow any errors as opposed to onSuccess which would propagate the failed task.

Changing this to onSuccess would be a breaking change in itself, but say we did change this to onSuccess the upstream caller ParseInstallation.getCurrentInstallation() swallows the error due to backwards compatibility and changing it to throw would be a another breaking change.

We could add logging, but without being able to reproduce it on a development device we won't have access to those logs.

@alexblack
Copy link
Author

"We could add logging, but without being able to reproduce it on a development device we won't have access to those logs."

Again, that is just one of many possible solutions if you're interested in helping.

If you're not willing to log it to your server, to somewhere you can check, then I can propose another option. Provide a hook for me to log it, and I'll log it to somewhere I can check.

@parse-github-bot
Copy link

This issue has not been updated for 7 days. If you have additional information to help pinpoint this issue as an SDK bug, please comment on this issue. We will close this issue in 7 days if no additional information is provided. Thank you for your feedback.

@parse-github-bot
Copy link

We are closing this issue due to another 7 days of inactivity. If you have additional information to help pinpoint this issue as an SDK bug, please reopen it with the additional information.Thank you for your feedback.

@alexblack
Copy link
Author

I suspect resetting the installation might solve this:

http://stackoverflow.com/questions/31890049/parse-push-notifications-how-to-reset-installation-data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants