Skip to content

Fix UnicodeEncodeError from non-ASCII EXIF metadata on export (#452)#454

Open
RP2 wants to merge 1 commit into
marcinz606:mainfrom
RP2:fix/452-ascii-encode-error
Open

Fix UnicodeEncodeError from non-ASCII EXIF metadata on export (#452)#454
RP2 wants to merge 1 commit into
marcinz606:mainfrom
RP2:fix/452-ascii-encode-error

Conversation

@RP2

@RP2 RP2 commented Jul 11, 2026

Copy link
Copy Markdown

Fixes #452 -- export crashes with UnicodeEncodeError when source EXIF metadata contains non-ASCII characters like the multiplication sign.

Root cause

_decode_ascii in negpy/features/metadata/writer.py is the single chokepoint for all EXIF string values flowing into tifffile.imwrite. Its str branch returned non-ASCII characters unchanged, and its bytes branch produced U+FFFD (also non-ASCII). When either reached tifffile.imwrite(description=...), tifffile's bare .encode('ascii') raised UnicodeEncodeError.

The error appeared as "Failed to load file" because the export worker's error signal connects to _on_render_error, which prefixes all messages with that string.

Fix

Make both branches round-trip through encode("ascii", "replace") then decode("ascii"), replacing non-ASCII characters with ?. Consistent with the existing _exif_ascii helper used for NegPy-authored metadata.

Files changed:

  • negpy/features/metadata/writer.py -- the fix
  • tests/metadata/test_writer.py -- 7 new tests

Verification

  • All tests in tests/metadata/test_writer.py pass (9 existing + 7 new)
  • New tests cover both branches, NULL bytes, None, and the exact crash scenario (non-ASCII in EXIF ImageDescription through embed_metadata)
  • Lint and format checks clean

_decode_ascii's str branch returned non-ASCII characters unchanged.
When this string reached tifffile.imwrite(description=...), tifffile's
.encode('ascii') raised UnicodeEncodeError, crashing export.

The bytes branch had the same issue -- decode('ascii', 'replace')
produces U+FFFD (replacement character), which is also non-ASCII and
would crash tifffile.

Fix both branches by round-tripping through encode/decode ASCII with
replacement, producing pure ASCII output with '?' as fallback.

Adds 7 tests covering both branches, edge cases, and the exact crash
scenario (non-ASCII in EXIF ImageDescription through embed_metadata).

Fixes marcinz606#452
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.

Exporting results in an error "failed to load file: 'ascii' codec can't encode character '\xd7' in position 27: ordinal not in range(128)"

1 participant