Skip to content

[Python] ParquetWriter doesn't support all valid s3 paths #46924

Open

Description

@graydenshand

Describe the bug, including details regarding any error messages, version, and platform.

It appears pyarrow.parquet.ParquetWriter doesn't accept s3 path that contain # despite that being a valid character in s3 paths.

>>> import pyarrow as pa
>>> import pyarrow.parquet as pq
>>> schema = pa.schema([pa.field("foobar", pa.string())])
>>> writer = pq.ParquetWriter('s3://my-bucket/a#b#c.parquet', schema=schema)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/project/.venv/lib/python3.12/site-packages/pyarrow/parquet/core.py", line 1014, in __init__
    sink = self.file_handle = filesystem.open_output_stream(
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "pyarrow/_fs.pyx", line 885, in pyarrow._fs.FileSystem.open_output_stream
  File "pyarrow/error.pxi", line 155, in pyarrow.lib.pyarrow_internal_check_status
  File "pyarrow/error.pxi", line 92, in pyarrow.lib.check_status
pyarrow.lib.ArrowInvalid: Expected a local filesystem path, got a URI: 's3://my-bucket/a#b#c.parquet'

Other special characters ([$*&@!])seem to be acceptable, so classifying this as a bug rather than a feature request.

via pyarrow v20.0.0

Possibly related to #41365.

Component(s)

Python

Activity

  1. changed the title [-](python) ParquetWriter doesn't support all valid s3 paths[/-] [+][Python] ParquetWriter doesn't support all valid s3 paths[/+] on Jun 28, 2025
  2. added
    Status: needs championHigh impact issues which aren't being worked on but require a volunteer to move the task forward.
    on Oct 26, 2026
  3. thisisnic commented on Oct 26, 2026

    @thisisnic
    Member

    Can reproduce on 26.0.0. Did a brief Claude analysis; looks like a mix of things which aren't percent encoded and error messages not surfacing:

    🤖 :

    The path is parsed as an RFC 3986 URI (uriparser, in cpp/src/arrow/util/uri.cc). In a URI # starts the fragment, and a second # inside a fragment is a syntax error, so s3://my-bucket/a#b#c.parquet fails with "Cannot parse URI ... syntax error at character '#'". The same happens for spaces and [/]. The characters that work ($*&@!) are all legal in a URI path.

    _resolve_filesystem_and_path() in python/pyarrow/fs.py catches that "Cannot parse URI" error and silently falls back to LocalFileSystem, which then rejects the string with the misleading "Expected a local filesystem path, got a URI" seen above. This is the same mechanism as #41365 (whitespace), which #49372 is fixing by raising a proper error instead of falling back.

    There is a worse case with a single #: s3://my-bucket/a#b.parquet parses fine, the fragment is dropped, and FileSystem.from_uri() returns key my-bucket/a, so a write would silently go to the wrong object. FileSystemFromUri() in cpp/src/arrow/filesystem/filesystem.cc should reject a non-empty fragment, since no filesystem uses one.

    Results on 26.0.0 via FileSystem.from_uri(): s3://my-bucket/a#b#c.parquet cannot parse; s3://my-bucket/a#b.parquet resolves to my-bucket/a; s3://my-bucket/a%23b%23c.parquet resolves to my-bucket/a#b#c.parquet; s3://my-bucket/a b.parquet and s3://my-bucket/a[b].parquet cannot parse; s3://my-bucket/a?b.parquet is rejected as an unexpected query parameter; $, *, &, @, ! all resolve correctly.

    Workaround: percent-encode the key (s3://my-bucket/a%23b%23c.parquet), or pass filesystem=S3FileSystem() with the plain key my-bucket/a#b#c.parquet. Neither the from_uri() docstring nor the filesystems docs currently say that URIs must be percent-encoded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Component: PythonStatus: needs championHigh impact issues which aren't being worked on but require a volunteer to move the task forward.Type: bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions