Skip to content

fix(files): check is_tuple_t before is_file_content to fix PathLike inside file tuples#1322

Open
IgnazioDS wants to merge 1 commit intoanthropics:mainfrom
IgnazioDS:fix/pathlike-in-file-tuple-1318
Open

fix(files): check is_tuple_t before is_file_content to fix PathLike inside file tuples#1322
IgnazioDS wants to merge 1 commit intoanthropics:mainfrom
IgnazioDS:fix/pathlike-in-file-tuple-1318

Conversation

@IgnazioDS
Copy link
Copy Markdown

Summary

Fixes #1318client.beta.files.upload crashes when a PathLike is passed as the second element of a file tuple (e.g. ("filename.txt", Path("foo.txt"), "text/plain")).

Root cause: is_file_content() returns True for any tuple, so the is_tuple_t branch in both _transform_file and _async_transform_file was unreachable. A file tuple hit the is_file_content branch first and was returned unchanged — the PathLike inside was never read via read_file_content.

# Before — is_file_content catches tuples, is_tuple_t is unreachable
def _transform_file(file: FileTypes) -> HttpxFileTypes:
    if is_file_content(file):   # True for tuples → returns tuple as-is
        ...
        return file              # PathLike inside tuple never read

    if is_tuple_t(file):        # UNREACHABLE for tuples
        return (file[0], read_file_content(file[1]), *file[2:])

Fix: Check is_tuple_t first in both the sync and async paths, so tuples with PathLike second elements are correctly read before being forwarded to httpx.

# After — tuple branch runs first
def _transform_file(file: FileTypes) -> HttpxFileTypes:
    if is_tuple_t(file):
        return (file[0], read_file_content(file[1]), *file[2:])  # PathLike read ✓

    if is_file_content(file):
        if isinstance(file, os.PathLike):
            ...
        return file

Same fix applied to _async_transform_file with async_read_file_content.

Test plan

  • ("filename.txt", Path("foo.txt"), "text/plain") — PathLike read, no crash
  • ("filename.txt", Path("foo.txt")) — 2-tuple variant works
  • Path("foo.txt") bare PathLike — still works (goes through is_file_content branch)
  • ("filename.txt", b"bytes", "text/plain") — bytes tuple still works
  • Run pytest tests/test_files.py

…ke in tuples (anthropics#1318)

is_file_content() returns True for tuples (bytes|tuple|io.IOBase|PathLike),
so the is_tuple_t branch in _transform_file and _async_transform_file was
unreachable. Any caller passing a file tuple whose second element is a
PathLike — e.g. ("filename.txt", Path("foo.txt"), "text/plain") — would
hit the is_file_content branch first, which returns the tuple unchanged
without ever calling read_file_content on the PathLike.

Fix: swap the guard order so is_tuple_t is checked first in both the
sync and async paths. The PathLike is then correctly read via
read_file_content / async_read_file_content before being forwarded to httpx.

Fixes anthropics#1318
@IgnazioDS IgnazioDS requested a review from a team as a code owner April 1, 2026 15:42
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