Skip to content

fix(files): resolve PathLike inside FileTypes tuples#1332

Open
qozle wants to merge 1 commit intoanthropics:mainfrom
qozle:fix/files-pathlike-in-tuple
Open

fix(files): resolve PathLike inside FileTypes tuples#1332
qozle wants to merge 1 commit intoanthropics:mainfrom
qozle:fix/files-pathlike-in-tuple

Conversation

@qozle
Copy link
Copy Markdown

@qozle qozle commented Apr 5, 2026

What

Fixes #1318.

is_file_content() in _files.py included isinstance(obj, tuple) in its check, but FileContent = Union[IO[bytes], bytes, PathLike[str]] — tuples are not file content, they are FileTypes variants (the (name, content, content_type[, headers]) forms).

This meant the is_tuple_t(file) branch in _transform_file and _async_transform_file was unreachable for any tuple input. Instead of calling read_file_content(file[1]) on the inner element, both functions returned the tuple unchanged. When that inner element was a PathLike, httpx received it as-is and failed.

Why it worked before (sort of)

Passing ("name", b"bytes") as a FileTypes value still produced a usable result because httpx accepts raw tuples with bytes. But ("name", Path("foo"), "text/plain") failed because httpx does not read PathLike objects — and the type annotation in _types.py explicitly promises PathLike is a valid FileContent.

Fix

Remove isinstance(obj, tuple) from is_file_content. Tuples now fall through to the is_tuple_t branch and get processed correctly — read_file_content / async_read_file_content resolves the PathLike to bytes before passing to httpx.

Also corrects the assert_is_file_content error message, which listed "or a tuple" as a valid FileContent form.

Tests

Added test_pathlike_in_tuple and test_async_pathlike_in_tuple which exercise the previously broken path. All existing tests pass.

# was silently broken
to_httpx_files({"file": ("report.pdf", Path("report.pdf"), "application/pdf")})
# now works correctly

`is_file_content()` included `isinstance(obj, tuple)` in its guard, but
`FileContent` is `Union[IO[bytes], bytes, PathLike[str]]` — tuples are
not file content, they're `FileTypes` variants. This made the
`is_tuple_t(file)` branch in `_transform_file` and
`_async_transform_file` unreachable for tuple inputs, so `PathLike`
objects in the second position of a `(name, PathLike, content_type)`
tuple were returned as-is instead of being read with
`read_file_content()`. httpx then received a `PathLike` where it
expected `bytes` or `IO[bytes]`.

Removing `isinstance(obj, tuple)` from `is_file_content` lets tuples
fall through to the correct `is_tuple_t` branch, which calls
`read_file_content(file[1])` and resolves the `PathLike`. Also corrects
the `assert_is_file_content` error message which incorrectly listed
tuples as valid `FileContent`.

Fixes anthropics#1318
@qozle qozle requested a review from a team as a code owner April 5, 2026 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] client.beta.files.upload PathLike error

1 participant