68
Error:Not sure how to convert a Cursor to this method's return type
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
Compilation failed; see the compiler error output for details.

Using Room I'm getting this error and I'd like to find out which method causes it.

I have multiple DAOs, with approximately 60 methods in total, and this error just popped up after adding a method (copy&pasted from another one that worked perfectly, just changed the field to set).

I could post the whole class of DAOs, but I'm asking for a way to know which method failed. I tried with Run with --stacktrace, Run with --info and --debug option, but none of these show any valuable information.

The method I added is a @Query UPDATE with Int return type, as suggested in the documentation

UPDATE or DELETE queries can return void or int. If it is an int, the value is the number of rows affected by this query.

EDIT: I'd like to add that I tried deleting the method, bringing the DAO back to the working state, but it still gives me this error.

EDIT2: Adding gradle console output because unreadable in comments:

error: Not sure how to convert a Cursor to this method's return type
error: Not sure how to convert a Cursor to this method's return type
2 errors

:app:compileDebugJavaWithJavac FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

* Get more help at https://help.gradle.org

BUILD FAILED in 22s
David Corsalini
  • 7,030
  • 7
  • 36
  • 61
  • 1
    what is the full error message from gradle console? – pskink Sep 27 '17 at 11:17
  • @pskink added the full error message to the question – David Corsalini Sep 27 '17 at 12:51
  • 1
    this is my method which compiles just fine: `@Query("SELECT * FROM user") LiveData> loadUsers();` when i change `List` to `Vector` for example i am getting: `UserDao.java:19: error: Not sure how to convert a Cursor to this method's return type LiveData> loadUsers();` in the **Gradle Console** window of android studio - note it shows `UserDao.java:19` which is a line location and also it prints the method that is wrong, more https://developer.android.com/studio/run/index.html#gradle-console – pskink Sep 27 '17 at 13:12
  • 1
    I'm building from Kotlin, maybe that's why I don't get the line? – David Corsalini Sep 27 '17 at 13:36
  • imho what you posted here is not gradle console output, are you sure you copied that error message from [gradle console](https://developer.android.com/studio/run/index.html#gradle-console)? – pskink Sep 27 '17 at 13:46
  • Edited question with gradle console output – David Corsalini Sep 27 '17 at 16:12
  • @DavidCorsalini Did you find any solution, I am also facing the same issue – user3853169 Jun 15 '18 at 09:35
  • @user3853169 clean re-build fixed the error for me. – pcforgeek Jun 16 '18 at 14:07
  • just to be sure. Are you returning `LiveData` or `MutableLiveData`? – kike Jun 20 '18 at 07:24
  • 4
    I encountered the same issue today (return type was rxjava2 Observable). The error message does not contain any info about where the problem could be. I hope google will make the error message more informative. At least it should print a method name or expected return type... – ntoskrnl Jun 20 '18 at 13:54

21 Answers21

89

Recently I've had the same problem but I was using Coroutines within the Dao function, e.g.:

@Query("SELECT * FROM Dummy")
suspend fun get(): LiveData<List<Dummy>>

And was unable to compile, but after removing the suspend everything worked just fine. It's not needed when returning LiveData. suspend and LiveData seem not to work together (as of now).

Jeehut
  • 15,556
  • 7
  • 54
  • 70
Danilo Lemes
  • 1,434
  • 10
  • 12
  • 1
    For `Co-routines` support, I added `implementation "androidx.room:room-coroutines:${versions.room}"` dependency, but Build failed saying **`ERROR: Failed to resolve: androidx.room:room-coroutines:2.2.1'**. – iCantC Oct 27 '19 at 08:02
  • 1
    This was my issue. When returning LiveData, you should not use a suspend function because they are incompatible (and not needed). – E.T. Dec 06 '19 at 18:03
  • @iCantC You can just import `implementation "androidx.room:room-ktx:$room_version"` which is the up-to-date variant on how to integrate coroutines support for Room. See also official docs: https://developer.android.com/jetpack/androidx/releases/room – Jeehut Dec 25 '19 at 14:29
  • it is good to know, Yeah it was the cause of my problem for me also. Thx. – Mohamed Feb 25 '20 at 14:41
  • 1
    FYI "room-coroutines" has been renamed to "room-ktx" as of [Version 2.1.0-alpha05](https://developer.android.com/jetpack/androidx/releases/room#2.1.0-alpha05). However, I already had this in my project and it did not fix the error. Removing `suspend` as per this answer did fix the error for me. – tytk Sep 06 '20 at 18:35
  • You answer saved my day. By reading android documentation i converted my DAO function to suspend function. Now i have to convert it back as non Suspend – Antroid Nov 26 '20 at 21:07
  • This link confirms this answer https://stackoverflow.com/questions/54566663/room-dao-livedata-as-return-type-causing-compile-time-error – Jeffrey May 25 '21 at 16:42
59

I Spend the entire day on this issue. the solution was very simple. I was using something like this before

@Query("SELECT * FROM myTable")
fun getAll(): MutableLiveData<ArrayList<myData>>

Now when I changed ArrayList to List & MutableLiveData to LiveData it is working fine.

@Query("SELECT * FROM myTable")
fun getAll(): LiveData<List<myData>>

based on the answers & comments on this issue I think room support only List & LiveData because I tried with on MutableLiveData & only ArrayList too. none of the combinations worked.

Hope this will help someones few hours.

akshay bhange
  • 1,786
  • 1
  • 20
  • 41
36

Yup, based on what you have mentioned in the comments, you are not allowed to change the return type from List to anything else inside the Dao. I'd assume Room doesn't know how to deal with other return types. Take the List and cast/convert it into your desired type outside of the Dao.

Ali Kazi
  • 1,406
  • 1
  • 15
  • 22
32

For anyone landing here, using a coroutine Flow as a return type, you will get this error if you accidentally make the function suspend. Since it is returning a flow, there is no need to suspend.

So instead of this:

@Query("SELECT * FROM myTable WHERE id = :id")
suspend fun findById(id: Long): Flow<MyDataType>

use this (without suspend modifier):

@Query("SELECT * FROM myTable WHERE id = :id")
fun findById(id: Long): Flow<MyDataType> 
gMale
  • 14,075
  • 17
  • 81
  • 109
5

In my case i was this problem when i used LiveData<ArrayList<Example Class>> in Dao class for getting all things from Room and i fixed this when i change ArrayList with List.

Example(Kotlin):

@Dao
interface ExampleDao {
@Query("SELECT * from example_table")
fun getAllExample():LiveData<List<Example>>
}
Fidan Bacaj
  • 370
  • 4
  • 8
3
@Query("select * from movie_action")
    suspend fun getMovieActionRoom() : LiveData<List<MoviesActionModel>>

just remove suspend and the error will be gone in some cases.

Felipe Franco
  • 117
  • 1
  • 12
2

For me it was because of mixing AndroidX with Pre-AndroidX. After a full migration and performing this, everything was back to normal. (Of course I moved to AndroidX-Room as well)

Tanasis
  • 719
  • 1
  • 9
  • 18
2

I've got a different use case for my apps.

So, I'm trying to return the actual Cursor type.

E.g:

@Query("SELECT * FROM tbl_favourite")
abstract suspend fun selectAll(): Cursor

The above code will always throw Error:Not sure how to convert a android.database.Cursor to this method's return type

But as I recall correctly, the official docs also stated here that Room supports Cursor.

After trying to debug the error log, and open up the MyTableDao_Impl.java file I've found that looks like Cursor are having an unhealthy relationship with suspend keywords.

Thus, I've corrected my code to be like this:

@Query("SELECT * FROM tbl_favourite")
abstract fun selectAll(): Cursor

And voila, it works.

mochadwi
  • 759
  • 8
  • 24
  • 75
2

in case someone actually needs MutableLiveData<List<T>> in their ViewModel when working with Room and using Kotlin and coroutines, this is how I've solved it

In the Dao I get MutableList with suspend
In the repository I change the context to Dispatchers.IO and extract the list with suspend
in the ViewModel I use postValue with the list in the init, syntax is below

ViewModel

    private val allItems = MutableLiveData<List<DocumentItem>>()
    init {
        viewModelScope.launch {
            allItems.postValue(repository.getAll())
        }
    }

Repository

    suspend fun getAll(): MutableList<DocumentItem> = withContext(Dispatchers.IO) {
        dao.getAll()
    }

Dao

    @Query("SELECT * FROM document_items ORDER BY id DESC")
    suspend fun getAll(): MutableList<DocumentItem>
Stachu
  • 1,109
  • 3
  • 14
1

Add the below code inside defaultConfig in build.gradle

javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true
Vijay
  • 333
  • 2
  • 11
1

Make sure you are not using suspend together with LiveData as return type:

@Query("SELECT * FROM ...")
fun getAllTellsByReceiver(receiverUid: String): LiveData<List<Tell>>
André Ramon
  • 872
  • 6
  • 20
1

In my case I was using androidx dependencies for Room and android.arch. [old] dependencies for ViewModel and LiveData so I got this message

Solution: Either use all androidx dependencies OR use all old dependencies of andrio.arch

Makarand
  • 623
  • 4
  • 16
0

For my case, after got "Not sure how to convert a Cursor to this method's return type”:

delete the "build" and re-build, the error disappear.

David Guo
  • 1,589
  • 3
  • 19
  • 30
0
 class IdAndFullName {
     public int uid;
     @ColumnInfo(name = "full_name")
     public String fullName;
 }
 // DAO
 @Query("SELECT uid, name || lastName as full_name FROM user")
 public IdAndFullName[] loadFullNames();

If there is a mismatch between the query result and the POJO, Room will give you this error message.

Or if you are using @SkipQueryVerification, you will also get this error.

live-love
  • 34,372
  • 16
  • 163
  • 152
0

Modify your Dao, use Flowable instead of observable and add the following dependency (room with rxjava support)

compile group: 'android.arch.persistence.room', name: 'rxjava2', version: '1.1.1'

Dao returns flowable:

@Query("SELECT * FROM TableX")
public abstract Flowable<List<EntityX>> getAllXs();
Mr.Q
  • 3,381
  • 3
  • 33
  • 34
0

For me it was to change from MutableLiveData to LiveData as the return type of the get method.

Otziii
  • 2,007
  • 1
  • 15
  • 29
0

For me, I was using wrong return type for queries.

Irshu
  • 7,251
  • 8
  • 45
  • 59
0

I got this error when I was trying do some aggregate functions in the query, like sum and count and then using aliases in the column names.

select count(users.id) as userCount, ...

It so happens that the alias name like userCount above, must match the field name in the model.

mike.kamau
  • 28
  • 6
0

You have to include the @Relation annotation in the class returned by the method. It's the only way Room would know how to establish the relationship between the two.

Aspiring Dev
  • 445
  • 4
  • 13
0

Make sure if there is

There is a problem with the query: [SQLITE_ERROR] SQL error or missing database (no such table: METRO)


error in your build log before the error you mentioned in your description. If it is, you may have forgotten to add your new entity Pojo to database class. something like this

@Database(entities = {Table.class,ForgottenTable.class}, version = 1) 
public abstract class Database extends RoomDatabase {
    //class codes
}
Reza
  • 498
  • 6
  • 10
0

In my case Room didn't know sure how to convert a Cursor to this method's return type i.e ArrayList so I changed a little bit I converted to list to kotlin's MutableListOf. Now it works fine.

gouri panda
  • 185
  • 1
  • 11