anthropics/skills · error · FileNotFoundError
{word} not found (not an unpacked .docx?)
Error message
{word} not found (not an unpacked .docx?) What it means
Raised by add_comment() (and its CLI wrapper in comment.py) when the unpacked directory does not contain a word/ subdirectory, which every real unpacked .docx must have. It signals the caller passed a directory that is not an unpacked OOXML package — e.g. a zip extracted from something other than a DOCX, or the parent of the unpacked tree.
Source
Thrown at skills/docx/scripts/comment.py:251
def add_comment(
unpacked_dir: Path | str,
text: str,
comment_id: int | None = None,
author: str = "Claude",
initials: str = "C",
parent_id: int | None = None,
raw: bool = False,
) -> tuple[int, str, str]:
unpacked_dir = Path(unpacked_dir)
if not raw:
text = xml_escape(text)
author = xml_escape(author, {'"': """})
initials = xml_escape(initials, {'"': """})
word = unpacked_dir / "word"
if not word.exists():
raise FileNotFoundError(f"{word} not found (not an unpacked .docx?)")
comments = word / "comments.xml"
if comment_id is None:
comment_id = _next_comment_id(comments)
parent_para = None
if parent_id is not None:
parent_para = _find_para_id(comments, parent_id) if comments.exists() else None
if not parent_para:
raise ValueError(f"parent comment {parent_id} not found")
para_id, durable_id = _generate_hex_id(), _generate_hex_id()
ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
if not comments.exists():
shutil.copy(TEMPLATE_DIR / "comments.xml", comments)
_ensure_comment_relationships(unpacked_dir)
_ensure_comment_content_types(unpacked_dir)View on GitHub (pinned to f6656c1256)
Solutions
- Unpack the DOCX first (e.g. 'unzip file.docx -d file_unpacked') and pass that directory so that file_unpacked/word exists.
- Check you passed the unpacked directory, not the .docx file path and not the parent of the unpacked tree.
- Confirm the source file is actually a DOCX ('unzip -l file.docx | grep word/document.xml').
- If using a custom unpack helper, verify it preserved internal structure rather than flattening entries.
Example fix
# before
add_comment(unpacked_dir=Path("report.docx"), text="note") # FileNotFoundError
# after
import zipfile, tempfile
with zipfile.ZipFile("report.docx") as zf, tempfile.TemporaryDirectory() as td:
zf.extractall(td)
add_comment(unpacked_dir=Path(td), text="note") Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def is_unpacked_docx(unpacked_dir: str | Path) -> bool:
return (Path(unpacked_dir) / "word").is_dir() and (Path(unpacked_dir) / "word" / "document.xml").exists() Try / catch
from pathlib import Path
try:
add_comment(unpacked_dir=d, text="note")
except FileNotFoundError as e:
if "not an unpacked .docx" in str(e):
raise RuntimeError(f"unpack {d} first: expected {d}/word to exist") from e
raise Prevention
- Always unpack to a dedicated temp directory and pass that directory.
- Assert (dir / 'word').is_dir() before calling docx helpers.
- Keep per-format tools separate: never point docx scripts at pptx/xlsx trees.
- Verify the unpack step succeeded (entry count > 0) before further processing.
When it happens
Trigger: Calling add_comment(unpacked_dir=...) (or the comment.py CLI with --raw/--unpacked-style flow) where unpacked_dir lacks a 'word' child: passing the .docx file path itself instead of the unpacked directory, passing the zip's root when it contains only 'ppt/' or 'xl/', or passing a directory that was never unpacked.
Common situations: Forgetting to run the unpack step before commenting; operating on PPTX/XLSX files with the docx tooling; passing the directory that CONTAINS the unpacked tree (one level too high); a previous unpack step failed silently leaving an empty directory.
Related errors
- parent comment {parent_id} not found
- relationship target is not a POSIX part name: {target!r}
- relationship target resolves to nothing: {target!r}
- relationship target escapes the package: {target!r}
- symlink archive entry not allowed: {m.filename!r}
AI-assisted analysis of anthropics/skills@f6656c1256 (2026-08-14).
Data as JSON: /api/errors/70b071be06bb7d95.
Report an issue: GitHub.