Name and Version
aidial-client 0.14.0 (also reproduces on 0.12.0)
What steps will reproduce the bug?
- Have a DIAL file whose name contains a space (or any URL-reserved character), e.g.
files/<bucket>/my file.txt.
- Call the move (or copy) operation:
from aidial_client import AsyncDial
client = AsyncDial(...)
await client.files.move_to(
source="files/<bucket>/my file.txt",
destination="files/<bucket>/renamed file.txt",
overwrite=False,
)
- DIAL Core responds with 500.
Root cause. move_to / copy_to place the resolved path into the JSON body verbatim, whereas every other file operation places it into the request URL:
# move_to / copy_to (resources/files.py) — path goes into the body
json_data={
"sourceUrl": self.get_api_path(str(source)), # 'files/<bucket>/my file.txt' ← raw space
"destinationUrl": self.get_api_path(str(destination)),
"overwrite": overwrite,
}
# upload / download / delete — path goes into the URL
url=urljoin(API_PREFIX, self.get_api_path(str(url)))
get_api_path returns the path unencoded (a literal space is preserved). For upload/download/delete that is harmless because httpx percent-encodes the URL path on the wire (my file.txt → my%20file.txt), so DIAL Core receives a valid resource URL. For move_to/copy_to the value sits in a JSON string, where nothing encodes it, so DIAL Core's ops/resource/move and ops/resource/copy endpoints receive a raw space in a field they parse as a percent-encoded resource URL, and 500.
Verification:
>>> from aidial_client.helpers.storage_resource import safe_parse_storage_resource
>>> safe_parse_storage_resource(url='files/mybucket/my file.txt', dial_api_url='http://core/v1/').api_path
'files/mybucket/my file.txt' # literal space kept — fine in a URL slot, broken in a body slot
Any URL-reserved character in a filename triggers this (space, #, ?, %, …), not only spaces.
What is the expected behavior?
move_to / copy_to succeed for any valid filename, consistent with upload / download / delete. The sourceUrl / destinationUrl values sent in the JSON body should be percent-encoded resource URLs (e.g. files/<bucket>/my%20file.txt), matching what DIAL Core receives for the other operations.
What do you see instead?
A 500 from DIAL Core whenever the source or destination path contains a space or other URL-reserved character. Filenames without reserved characters work correctly.
Additional information
The other file operations avoid the problem only incidentally, because httpx encodes the URL path — the body path is never encoded. A fix should percent-encode the path when building the sourceUrl / destinationUrl body fields for both the sync and async move_to / copy_to, preserving / separators (e.g. urllib.parse.quote(path, safe="/")).
Affected: both Files (sync) and AsyncFiles in aidial_client/resources/files.py.
Name and Version
aidial-client 0.14.0 (also reproduces on 0.12.0)
What steps will reproduce the bug?
files/<bucket>/my file.txt.Root cause.
move_to/copy_toplace the resolved path into the JSON body verbatim, whereas every other file operation places it into the request URL:get_api_pathreturns the path unencoded (a literal space is preserved). Forupload/download/deletethat is harmless because httpx percent-encodes the URL path on the wire (my file.txt→my%20file.txt), so DIAL Core receives a valid resource URL. Formove_to/copy_tothe value sits in a JSON string, where nothing encodes it, so DIAL Core'sops/resource/moveandops/resource/copyendpoints receive a raw space in a field they parse as a percent-encoded resource URL, and 500.Verification:
Any URL-reserved character in a filename triggers this (space,
#,?,%, …), not only spaces.What is the expected behavior?
move_to/copy_tosucceed for any valid filename, consistent withupload/download/delete. ThesourceUrl/destinationUrlvalues sent in the JSON body should be percent-encoded resource URLs (e.g.files/<bucket>/my%20file.txt), matching what DIAL Core receives for the other operations.What do you see instead?
A 500 from DIAL Core whenever the source or destination path contains a space or other URL-reserved character. Filenames without reserved characters work correctly.
Additional information
The other file operations avoid the problem only incidentally, because httpx encodes the URL path — the body path is never encoded. A fix should percent-encode the path when building the
sourceUrl/destinationUrlbody fields for both the sync and asyncmove_to/copy_to, preserving/separators (e.g.urllib.parse.quote(path, safe="/")).Affected: both
Files(sync) andAsyncFilesinaidial_client/resources/files.py.