msgraph-sdk-python icon indicating copy to clipboard operation
msgraph-sdk-python copied to clipboard

Error 400 during put on drive item

Open PrzemyslawSagalo opened this issue 1 year ago • 5 comments

Describe the bug

I am trying to upload a .docx file into OneDrive using Graph API. Unfortunately, it returns an error 400.

msgraph.generated.models.o_data_errors.o_data_error.ODataError:
{
APIError
Code: 400
error: MainError(code='BadRequest', message='Entity only allows writes with JSON Content-Type header.')
}

Expected behavior

Based on the type from the code of the sdk passed type is correct, so I don't understand this behaviour and the bellow code should upload the file.

How to reproduce

file_path = "test.docx"
with open(file_path, "rb") as file_handle:
    file_bytes = file_handle.read()

item_path = "/root:/Documents/test_on_one_drive.docx"
r = await client.drives.by_drive_id(drive_id).items.by_drive_item_id(item_path).content.put(body=file_bytes)

SDK Version

1.4.0

Latest version known to work for scenario above?

No response

Known Workarounds

No response

Debug output

Click to expand log ```
</details>


### Configuration

_No response_

### Other information

_No response_

PrzemyslawSagalo avatar Jun 03 '24 12:06 PrzemyslawSagalo

Hello @PrzemyslawSagalo thanks for using the SDK and for raising this.

What is the requestInformation, does it set the apprpriate content headers.

prior to sending the request, you might consider setting the request information object https://github.com/microsoft/kiota-abstractions-python/blob/main/kiota_abstractions/request_information.py

Then use that request information object for the request e.g to upload an item to drive?

Is the intention to upload an item to drive item https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=http or to update the properties of a drive item https://learn.microsoft.com/en-us/graph/api/driveitem-update?view=graph-rest-1.0&tabs=http?

shemogumbe avatar Jun 03 '24 13:06 shemogumbe

Hi @shemogumbe thank you for your quick response.

  1. Where exactly should I put/use this request information object? This is my client init stage.
proxies = {"http": "http://my-proxy.com:80", "https": "http://my-proxy.com:443"}

tenant_id = "tenant_id_value"
client_id = "client_id_value"

credentials = DeviceCodeCredential(client_id=client_id, tenant_id=tenant_id, proxies=proxies)

scopes = ["Files.ReadWrite.All"]

auth_provider = AzureIdentityAuthenticationProvider(credentials, scopes=scopes)

httpx_proxies = {
    "http://": proxies["http"],
    "https://": proxies["https"],
}

http_client = AsyncClient(proxies=httpx_proxies)
http_client = GraphClientFactory.create_with_default_middleware(client=http_client)
request_adapter = GraphRequestAdapter(auth_provider, http_client)
client = GraphServiceClient(request_adapter=request_adapter)
  1. My intention is to upload a new file to OneDrive as it is here: https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=http#to-upload-a-new-file

PrzemyslawSagalo avatar Jun 03 '24 14:06 PrzemyslawSagalo

@shemogumbe The problem was in the wrong construction of the item_path. It should be root:/Documents/test_on_one_drive.docx: instead of /root:/Documents/test_on_one_drive.docx.

The exception message could be more intuitive because it does not accurately convey the actual problem.

PrzemyslawSagalo avatar Jun 04 '24 19:06 PrzemyslawSagalo

@PrzemyslawSagalo I had your same problem using almost the same code, and after fixing the item_path with the missing : char I get another error:

APIError Code: 400 message: None error: MainError(additional_data={}, code='invalidRequest', details=None, inner_error=InnerError(..., message='A valid name must be provided.', target=None)

Did you happen to solve this too?

My code is:

async with aiofiles.open(src_file_path, 'rb') as file:
    file_content = await file.read()

dest_file_path = f"{dest_folder_name}/{src_file_name}"
drive_item_id = f"root:/{dest_file_path}/:"
uploaded_file = await self.client.drives.by_drive_id(drive_id).items.by_drive_item_id(drive_item_id).content.put(file_content)

What can I try to solve this? @shemogumbe

Thank you.

LuchiLucs avatar Sep 10 '24 10:09 LuchiLucs

Solved, there was a missing /, i.e. drive_item_id = f"/root:/{dest_file_path}/:"

LuchiLucs avatar Sep 10 '24 10:09 LuchiLucs