sdk-for-android
sdk-for-android copied to clipboard
🐛 Bug Report: Getting java.lang.NullPointerException when using Query.select on attributes along with limit query
👟 Reproduction steps
- Call the
listDocumentsfunction with parameters that include database and collection IDs, a numeric limit, and a list of attributes. - Include attribute selection in the query, where attribute names are passed dynamically to the
Query.selectmethod. - Execute the function, which internally calls
toJson()on the Query object.
👍 Expected behavior
Expected Behavior: The function should handle null values gracefully and not attempt to cast nulls to non-null strings. If a parameter is null, it should either be managed by default values or handled with appropriate error messages.
👎 Actual Behavior
Actual Behavior:
The application throws a java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String during the execution of the toJson() method in the Query class. This error suggests that there might be issues with how null values are being managed within query parameters or during their serialization/deserialization process.
🎲 Appwrite version
Version 1.5.x
💻 Operating system
Linux
🧱 Your Environment
No response
👀 Have you spent some time to check if this issue has been raised before?
- [X] I checked and didn't find similar issue
🏢 Have you read the Code of Conduct?
- [X] I have read the Code of Conduct
Android SDK version I am using is 5.1.1
@bigraymasoom Thanks for raising this issue. Sorry about taking this long. The team will verify if the issue still persists and get back to this 👍
Thanks, will surely wait for this. If its implemented i will be able to just get data for specific attributes in android instead of getting the whole data and the filtering the required one.
@ChiragAgg5k This is my complete discussion with gemini on this matter
Thank you for providing the source code for the Query class. This is the final piece of the puzzle, and it allows for a definitive explanation of everything we've observed.
After analyzing this code, my previous conclusion is strongly reinforced. Let's break down what this code reveals.
The Key Insight: Query is Just a String Builder
The single most important thing to understand about this class is that it does not perform any queries itself. Its only job is to create specially formatted strings.
Look at the signature of every static method:
fun equal(...) = Query(...).toJson()fun limit(...) = Query(...).toJson()fun select(...) = Query(...).toJson()
Each method does two things:
- It creates a new, temporary
Queryobject (e.g.,Query(method="select", attribute=null, values=listOf("title", "year"))). - It immediately calls
.toJson()on that object, which converts it into a string likeselect(["title", "year"]).
This string is the only thing that gets returned. The listDocuments and getDocument functions simply take a List<String> of these formatted query strings and pass them directly to the Appwrite server in the API request.
How This Explains Both Errors Perfectly
Now we can see the full picture and understand why the two different errors happened.
1. The Attribute not found in schema: $collectionId Error
- Your Code: Your extension called
databases.listDocumentswith a list containing the string returned byQuery.select(listOf("$id", "$collectionId", "title")). - What the SDK Did: It took that string (
select(["$id", "$collectionId", "title"])) and sent it to the Appwrite server. - What the Server Did: The server received the request. Its code for handling the
selectparameter is designed to only look at your collection's defined attributes (your schema). It saw"$collectionId", checked your schema, didn't find it, and correctly returned an error. - Conclusion: The
Query.selectmethod is just a dumb pipe. It passes whatever you give it to the server. The server correctly rejects requests for system attributes viaselect.
2. The NullPointerException (The Original Crash)
- Your Code: Your extension called
databases.listDocumentswith the string fromQuery.select(listOf("title")). - What the SDK Did: It sent the string
select(["title"])to the server. - What the Server Did: The server received this valid request. It found the matching documents and, to be efficient, returned only the
titlefor each one. The response looked like{"documents": [{"title": "Avatar"}, {"title": "Lord of the Rings"}]}. - What the SDK Did Next: The SDK received this minimal response. It then tried to create
Documentobjects from it using theDocument.from()parser we analyzed earlier. That parser requires the$id,$collectionId, etc., fields to be present. Since they were missing from the server's response, it tried to castnullto aStringand crashed.
Final, Definitive Recommendation for Your Extension
The source code for Query, Document, and DocumentList confirms the "Catch-22" situation:
- To use
Query.select, you cannot include system attributes ($id, etc.). - To use the SDK's automatic parsing into
Documentobjects, you must have the system attributes.
These two conditions are mutually exclusive. You cannot satisfy both at the same time.
Therefore, the only robust and correct solution for your MIT App Inventor extension is the one outlined in my previous response:
- Do Not Expose
Query.select: Remove theselectAttributesparameter from yourListDocumentsandGetDocumentblocks. They should always fetch the full document data. This avoids both types of errors. - Provide a Client-Side Helper Block: Add the new block
SelectAttributesFromDocument(document, keysToSelect). This block will run on the user's device. - Instruct Your Users: Teach them to first call
GetDocumentorListDocuments, and then use the new helper block on the result to filter down to the data they need.
This approach is safe, reliable, and gives your users the functionality they want without any risk of crashing the app.
Is this bug still open or fixed?
@bigraymasoom its in cycle to be fixed. sharing a small reproducible example will really help us solve this quicker, can you please share one?
@ChiragAgg5k Sorry with the late reply buddy. Here is the brief discussion about this error.
https://discord.com/channels/564160730845151244/1255448380033863690