pythongoogle-drive-apicopydrive

'The provided file ID is not usable.' when using drive API with python script to copy a file


I am trying to write python scripts to copy and edit files on Google drive using Drive API and a service account for permission purposes.

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import MediaFileUpload
from google.oauth2.service_account import Credentials

def copy_file_to_folder(file_id, destination_folder_id):

    creds = Credentials.from_service_account_file('service_account.json')
    
    try:
        service = build('drive', 'v3', credentials=creds)
        file = service.files().get(fileId=file_id).execute()
        file['parents'] = [destination_folder_id]
        copied_file = service.files().copy(fileId=file_id, body=file, fields='id').execute()
        return copied_file['id']
        
    except HttpError as error:
        print(f'An error occurred: {error}')
        return None
        
if __name__ == "__main__":
    file_id = 'File ID I wanted to copy'
    destination_folder_id = 'Destination folder ID to put the copy in'
    copy_file_to_folder(file_id, destination_folder_id)

This script when ran, returns the following error:

An error occurred: <HttpError 400 when requesting https://www.googleapis.com/drive/v3/files/[File ID]/copy?fields=id&alt=json returned "The provided file ID is not usable.". Details: "[{'message': 'The provided file ID is not usable.', 'domain': 'global', 'reason': 'fileIdNotUsable', 'location': 'file.id', 'locationType': 'other'}]">

I tried multiple files, I am even sharing the files for anyone with the link as an editor. Nothing worked, no ID worked.


Solution

  • From your showing error message The provided file ID is not usable., I guessed that the reason for your current issue might be due to that file of body=file includes id. In your script, file has kind, id, name, mimeType, parents. id is the ID of the source file. The file cannot be copied using the same ID. I guessed that this might be the reason for your current issue.

    In order to avoid this issue, how about the following modification? Please modify copy_file_to_folder as follows.

    Pattern 1:

    In this pattern, id is removed from file.

    def copy_file_to_folder(file_id, destination_folder_id):
    
        creds = Credentials.from_service_account_file('service_account.json')
        
        try:
            service = build('drive', 'v3', credentials=creds)
            file = service.files().get(fileId=file_id).execute()
            file['parents'] = [destination_folder_id]
            del file['id'] # Added
            copied_file = service.files().copy(fileId=file_id, body=file, fields='id').execute()
            return copied_file['id']
            
        except HttpError as error:
            print(f'An error occurred: {error}')
            return None
    

    Pattern 2:

    In this pattern, body is created.

    def copy_file_to_folder(file_id, destination_folder_id):
    
        creds = Credentials.from_service_account_file('service_account.json')
        
        try:
            service = build('drive', 'v3', credentials=creds)
            file = service.files().get(fileId=file_id).execute()
            body = {'name': file['name'], 'parents': [destination_folder_id]} # Added
            copied_file = service.files().copy(fileId=file_id, body=body, fields='id').execute() # Modified
            return copied_file['id']
            
        except HttpError as error:
            print(f'An error occurred: {error}')
            return None
    

    Note:

    Reference: