You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
profiling.sampling in --binary mode raises a UnicodeEncodeError while collecting the samples #160601
when trying to profile building xarray's docs with profiling.sampling I get a UnicodeEncodeError while collecting the result.
For now, the command to reproduce is:
git clone https://github.com/pydata/xarray
cd xarray
pixi run -e doc python -m profiling.sampling run --binary -o profile.bin -m sphinx -b html -d _build/doctrees . _build/html
And the traceback is:
Traceback (most recent call last):
File "<frozen runpy>", line 201, in _run_module_as_main
File "<frozen runpy>", line 87, in _run_code
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/__main__.py", line 65, in <module>
main()
~~~~^^
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/cli.py", line 1011, in main
_main()
~~~~~^^
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/cli.py", line 1167, in _main
handler(args)
~~~~~~~^^^^^^
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/cli.py", line 1316, in _handle_run
collector = sample(
process.pid,
...<9 lines>...
blocking=args.blocking,
)
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/sample.py", line 535, in sample
profiler.sample(collector, duration_sec, async_aware=async_aware)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/sample.py", line 192, in sampleraise e fromNone
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/sample.py", line 180, in sample
collector.collect(stack_frames)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File ".../xarray/.pixi/envs/doc/lib/python3.15/profiling/sampling/binary_collector.py", line 112, in collectself._writer.write_sample(stack_frames, timestamp_us)
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^UnicodeEncodeError: 'utf-8' codec can't encode character '\uddd0' in position 240: surrogates not allowed
I'm fully aware that this isn't a very minimal reproducer, but I didn't manage to find a minimal example as everything else I tried does not fail.
If you need more information or have any ideas on how to narrow this down I'd be happy to help.
A minimal way to trigger the same error, in case it helps. On Linux, Python decodes a file name that isn't valid UTF-8 with surrogateescape, so a script in such a directory has a co_filename containing a lone surrogate:
This fails with the same traceback, ending in UnicodeEncodeError: 'utf-8' codec can't encode character '\udce9' in position 23: surrogates not allowed, and leaves a 64-byte out.bin that replay rejects. --pstats profiles the same script without error. A function whose co_name contains a lone surrogate fails the same way. Reproduced with 3.15.1 and 3.16.0a1 on Linux.
The cause appears to be (links at main, 94942ba):
The binary writer encodes file and function names with PyUnicode_AsUTF8AndSize, which rejects lone surrogates.
BinaryCollector.collect catches only OverflowError, and the sampling loop treats a UnicodeDecodeError, but not a UnicodeEncodeError, as a failed sample, so the error ends the profile before the file is finalized.
The '\uddd0' in your traceback is outside U+DC80–U+DCFF, the only range surrogateescape produces, so in your run the surrogate came from somewhere other than a file name decoded that way. Either way, the writer would need to accept any str, for example by encoding with surrogatepass or backslashreplace; the reader already decodes with "replace".
I used an AI assistant (GitHub Copilot CLI) to narrow this down and write the reproducer, and I've reviewed the above.
looks like it is worse than that: with a debugger I can see a stack frame where the function name contains CJK characters as well as \xXX and \uXXXX sequences in a seemingly random order. And copy-pasting that function name into a separate python process and trying to encode as utf-8 results in the exact same error message.
the exact name is truncated just in case this is some kind of memory dump, but it has a length of 1024 chars (not bytes)
That's obviously not valid python and it definitely does not appear anywhere in my code, so I really wonder where this is coming from.
I can't confirm this reliably, but it looks like this only happens if I run the command when there's no previous binary output file existing, if it does the weird stack frame does not appear and the output file is written successfully.
Activity
patrick-5546 commentedon Oct 24, 2026
A minimal way to trigger the same error, in case it helps. On Linux, Python decodes a file name that isn't valid UTF-8 with
surrogateescape, so a script in such a directory has aco_filenamecontaining a lone surrogate:This fails with the same traceback, ending in
UnicodeEncodeError: 'utf-8' codec can't encode character '\udce9' in position 23: surrogates not allowed, and leaves a 64-byteout.binthatreplayrejects.--pstatsprofiles the same script without error. A function whoseco_namecontains a lone surrogate fails the same way. Reproduced with 3.15.1 and 3.16.0a1 on Linux.The cause appears to be (links at main, 94942ba):
PyUnicode_AsUTF8AndSize, which rejects lone surrogates.BinaryCollector.collectcatches onlyOverflowError, and the sampling loop treats aUnicodeDecodeError, but not aUnicodeEncodeError, as a failed sample, so the error ends the profile before the file is finalized.The
'\uddd0'in your traceback is outside U+DC80–U+DCFF, the only rangesurrogateescapeproduces, so in your run the surrogate came from somewhere other than a file name decoded that way. Either way, the writer would need to accept anystr, for example by encoding withsurrogatepassorbackslashreplace; the reader already decodes with"replace".I used an AI assistant (GitHub Copilot CLI) to narrow this down and write the reproducer, and I've reviewed the above.
keewis commentedon Oct 24, 2026
looks like it is worse than that: with a debugger I can see a stack frame where the function name contains CJK characters as well as
\xXXand\uXXXXsequences in a seemingly random order. And copy-pasting that function name into a separate python process and trying to encode as utf-8 results in the exact same error message.FrameInfo repr extracted using a debugger
the exact name is truncated just in case this is some kind of memory dump, but it has a length of 1024 chars (not bytes)
That's obviously not valid python and it definitely does not appear anywhere in my code, so I really wonder where this is coming from.
I can't confirm this reliably, but it looks like this only happens if I run the command when there's no previous binary output file existing, if it does the weird stack frame does not appear and the output file is written successfully.