Google Drive API throws IllegalArgumentException when trying to access file by ID

I’m working on an Android app that integrates with Google Drive API. I followed the official documentation and examples but I’m stuck with a frustrating issue.

My app can successfully create folders, upload files, and run search queries. But when I try to download a file, I get an error saying “Id must be provided” even though I’m passing what looks like a valid file ID.

Here’s what happens:

  1. First I search for files with a specific name using a query.
  2. I get back results that include DriveId objects like this:
DriveId:CAESHDBC4k2x9s5ZlnUMEsxUGt6NHAzaFkYhgggmNuW1qxR
File: myDocument.txt
DriveId:CAESHDBC4k2x9s5ZlnUdj8uTXp4cmpoPqYhg_gcgmNuW1qxR  
File: myDocument.txt
  1. I extract the ID string and pass it to the file download method.
  2. The crash happens when calling DriveFile file = Drive.DriveApi.getFile(apiClient, driveId).

Here’s my download implementation:

public class DriveFileDownloader extends BaseDriveActivity {
    private String fileIdentifier;

    @Override
    public void onConnected(Bundle hint) {
        super.onConnected(hint);
        Query searchQuery = new Query.Builder()
                .addFilter(Filters.eq(SearchableField.MIME_TYPE, "text/plain"))
                .addFilter(Filters.eq(SearchableField.TITLE, "myDocument.txt"))
                .build();
        Drive.DriveApi.query(getGoogleApiClient(), searchQuery)
                .setResultCallback(searchCallback);
    }

    final private ResultCallback<MetadataBufferResult> searchCallback = 
            new ResultCallback<MetadataBufferResult>() {
        @Override
        public void onResult(MetadataBufferResult result) {
            MetadataBuffer files = result.getMetadataBuffer();
            if (files.getCount() > 0) {
                String driveIdString = files.get(files.getCount() - 1)
                        .getDriveId().toString();
                fileIdentifier = driveIdString.replace("DriveId:", "");
            }
            files.close();
            Drive.DriveApi.fetchDriveId(getGoogleApiClient(), fileIdentifier)
                    .setResultCallback(idCallback);
        }
    };

    private class FileContentTask extends ApiClientAsyncTask<DriveId, Boolean, String> {
        @Override
        protected String doInBackgroundConnected(DriveId... params) {
            DriveFile targetFile = Drive.DriveApi.getFile(getGoogleApiClient(), params[0]);
            // Error occurs here
            ContentsResult contentResult = targetFile.openContents(
                    getGoogleApiClient(), DriveFile.MODE_READ_ONLY, null).await();
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    contentResult.getContents().getInputStream()));
            StringBuilder content = new StringBuilder();
            String currentLine;
            try {
                while ((currentLine = reader.readLine()) != null) {
                    content.append(currentLine);
                }
            } catch (IOException e) {
                Log.e("file_download", "Failed to read file content", e);
            }
            return content.toString();
        }
    }
}

The error stacktrace shows:

java.lang.IllegalArgumentException: Id must be provided.
at com.google.android.gms.drive.internal.l.getFile(Unknown Source)

What am I doing wrong with the DriveId handling? How should I properly convert the search results into a usable file reference for downloading?

I encountered this exact same issue last year when working with Drive API v2. The problem is in how you’re handling the DriveId object after the search callback. You’re converting it to string and then stripping the ‘DriveId:’ prefix, but that destroys the internal structure that the API needs. Instead of extracting the string representation, you should pass the actual DriveId object directly to your FileContentTask. Modify your searchCallback to store the DriveId object itself, not its string representation. So instead of doing the string manipulation, just use DriveId actualDriveId = files.get(files.getCount() - 1).getDriveId() and pass that object directly. Also, you don’t need the fetchDriveId call at all since you already have a valid DriveId from the search results. That’s actually adding unnecessary complexity and potential failure points to your flow.

looks like youre overcomplicating the driveId handling. the issue is when you call .toString() on the driveId and then try to use fetchDriveId - just skip all that string manipulation stuff. directly use the driveId object from your search results in the FileContentTask instead of converting it back and forth.