[BUG] docx skill validator crashes with UnicodeDecodeError on Windows (missing encoding="utf-8" in validators/base.py)

Status Open
Reported on v2.1.236
Maintainer reply None cached
Activity 0 comments · opened Aug 31, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

The built-in docx skill's XSD validation step (scripts/office/validators/base.py,
_validate_single_file_xsd) opens each unpacked Office XML file with open(xml_file, "r") — no
encoding argument. On Windows, Python's text-mode open() defaults to the OS locale codepage
(e.g. cp1252 on a US-English Windows install), not UTF-8. Every OOXML part (word/document.xml, etc.)
is UTF-8-encoded and routinely contains UTF-8 multi-byte sequences (em dashes, checkbox glyphs, curly
quotes, etc.), so reading it under cp1252 either raises a UnicodeDecodeError or silently mis-decodes
those bytes. This makes validate.py fail on every Windows docx-generation run that produces such
characters — which is most of them — even when the actual edits/XML are completely correct.

What Should Happen?

_validate_single_file_xsd should open XML files with an explicit encoding="utf-8" (OOXML parts are
always UTF-8 per the ECMA-376/ISO-29500 spec, so this isn't locale-dependent data — it should never have
been left to the platform default). With that one change, validation succeeds correctly on Windows for
documents that are otherwise well-formed.

Error Messages/Logs

UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position <N>: character maps to <undefined>

(exact byte/position varies by document content — triggered by any UTF-8 multi-byte character, e.g. an
em dash `—` or a checkbox glyph, landing in a byte range that `cp1252` doesn't map).

Steps to Reproduce

  1. On a Windows machine with the default US-English locale (codepage 1252), use the built-in docx

skill to create or edit a .docx containing a non-ASCII character that's multi-byte in UTF-8 (e.g. an
em dash —, curly quotes, or a checkbox glyph ☐).

  1. Let the skill run its validation step: python scripts/office/validate.py out.docx --original doc.docx

(or the equivalent invoked automatically as part of the skill's normal edit→repackage→validate flow).

  1. Observe the validator crash with a UnicodeDecodeError (or silent mis-decoding) while parsing

word/document.xml, even though the document's actual edits are correct and well-formed.

  1. Confirm this is a Windows-default-encoding issue, not a real document problem — re-reading the same

file with encoding="utf-8" explicitly parses it without error.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

N/A (not a known regression).

Claude Code Version

2.1.236 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

Regression Status

Not sure whether this ever worked on Windows — this looks like it's been broken since the skill's
validator was written, since Python's open() has always defaulted to the locale codepage on Windows.
Not something I've seen reported as "used to work."

Terminal/Shell

<!-- Confirm before submitting — repro was via Claude Desktop's Code tab; pick the closest match from
the issue form's dropdown, or select "Other" and note "Claude Desktop (Code tab)" -->
Other (Claude Desktop, Code tab)

Additional Information

Exact file and line: scripts/office/validators/base.py, inside _validate_single_file_xsd:

# Current (buggy on Windows):
with open(xml_file, "r") as f:
    xml_doc = lxml.etree.parse(f)

# Fix:
with open(xml_file, "r", encoding="utf-8") as f:
    xml_doc = lxml.etree.parse(f)

I checked the rest of the docx skill's scripts (merge_runs.py, comment.py, accept_changes.py,
office/helpers/) for the same pattern and this appears to be the only occurrence of an un-encoded text
open() on an XML file — every other file read/write already specifies "rb"/"wb" or an explicit
encoding.

Separately (not filing as part of this report, just context): the skill's own dependency list
(SKILL.md) names pandoc, LibreOffice (soffice), and pdftoppm (Poppler) as expected tools for
rendering-to-PDF visual QA, tracked-changes merging, and legacy .doc conversion. None of these ship on
a bare Windows install, so those specific features fail with "command not found" rather than a
Windows-specific bug — that's expected/by-design for an unconfigured machine, not something I'm asking to
be fixed here, just flagging in case it's useful context for how Windows users experience this skill.

View original on GitHub ↗