dropbox / dropbox/dropbox-sdk-rust
Fails to refresh API token due to API quirk (unlike Python SDK)
- Dominant language
- Rust
- Stars
- 91
- Forks
- 19
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
The Dropbox API has a peculiar quirk where it wraps an authentication error on content endpoints such as `files/upload` and `files/download` into `"other"`, losing the actual structured error classification. For example, for an expired token it would normally be `"expired_access_token"`.
**To Reproduce**
The actual error is instead JSON-encoded inside `user_message.text`. This can be reproduced directly with curl:
```sh
BAD='sl.this-is-not-a-valid-dropbox-token-0123456789012345678901234567890123456789'
curl -sS https://api.dropboxapi.com/2/files/get_metadata \
-H "Authorization: Bearer $BAD" \
-H 'Content-Type: application/json' \
-d '{"path":"/does-not-exist"}'
printf test | curl -sS https://content.dropboxapi.com/2/files/upload \
-H "Authorization: Bearer $BAD" \
-H 'Dropbox-API-Arg: {"path":"/does-not-exist"}' \
-H 'Content-Type: application/octet-stream' \
--data-binary @-
```
**Expected Behavior**
Either the Rust SDK handles the above by unwrapping, or the API returns something that isn't `"other"`.
**Actual Behavior**
The first request returns:
```json
{"error":{".tag":"invalid_access_token"},"error_summary":"invalid_access_token/"}
```
The content request returns:
```json
{
"error": {".tag": "other"},
"error_summary": "other/...",
"user_message": {
"locale": "en",
"text":
"{\"error\":{\".tag\":\"invalid_access_token\"},\"error_summary\":\"invalid_access_token/\"}"
}
}
```
The same wrapping has been observed for `"expired_access_token"`.
**Versions**
* Reproduced with `dropbox-sdk` 0.20.3.
* Rust 1.97.1
* Linux 6.18.44, x86-64, NixOS 26.05
**Additional context**
This behavior has also been mentioned in a forum post at:
The Rust SDK does support automatic token refresh after receiving `ExpiredAccessToken`, which gets masked by the `Other` wrapping. It lacks proactive expiration-based refresh, unlike e.g. the Python SDK.
Someone writing code will likely assume `Other` is not fixable by refreshing a token and thus have an app that does not survive the four-hour token lifetime if its first request after expiry is a content request (ask me how I know!).
I'm not sure what the best fix is. It could be any of:
- Dropbox fixing its upstream API
- Adding proactive automatic token refresh to the Dropbox SDK, which may or may not be feasible depending on its structure
- Unwrapping other errors by trying to deserialize the contents of `user_message.text` in the Rust SDK
In the meantime, treating `Other` as an expired token in the consuming app and performing a bounded refresh-and-retry works, but I shudder to think what happens if an actual `Other` error comes around.
Contributor guide
Research direction
Reproduce the discrepancy with the supplied curl requests against files/get_metadata and files/upload, then trace how the Rust SDK handles Other and ExpiredAccessToken responses. Compare the available approaches—unwrapping user_message.text, proactive refresh, or another bounded retry strategy—and define done as preserving correct token-refresh behavior without misclassifying genuine Other errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, authentication
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100