anthropics/skills · error · ValueError

relationship target resolves to nothing: {target!r}

Error message

relationship target resolves to nothing: {target!r}

What it means

opc_target() raises this when a non-empty relationship target normalizes to an empty part name — every segment was '.', empty, or consumed by '..' pops (e.g. Target='.', Target='./', or 'a/..'). OPC requires each relationship to name a real part; an empty resolution means the .rels entry is corrupt. Exists in both the docx and pptx copies of office/helpers/__init__.py.

Source

Thrown at skills/docx/scripts/office/helpers/__init__.py:54

    if target.startswith("/"):
        joined = target.lstrip("/")
    else:
        joined = posixpath.join(posixpath.dirname(source_part), target)

    parts: list[str] = []
    for segment in posixpath.normpath(joined).split("/"):
        if segment in ("", "."):
            continue
        if segment == "..":
            if not parts:
                raise ValueError(f"relationship target escapes the package: {target!r}")
            parts.pop()
        else:
            parts.append(segment)

    if not parts:
        raise ValueError(f"relationship target resolves to nothing: {target!r}")
    return "/".join(parts)


def rels_source_part(rels_file: Path, unpacked_dir: Path) -> str:
    owner_dir = rels_file.parent.parent.relative_to(unpacked_dir)
    return posixpath.join(owner_dir.as_posix(), rels_file.name[: -len(".rels")]).lstrip("./")


def part_text(data: bytes) -> str:
    return data.decode("utf-8", "surrogateescape")


XML_SPACE = " \t\r\n"


def rendered_text(text: str, preserve: bool) -> str:
    return text if preserve else text.strip(XML_SPACE)

View on GitHub (pinned to f6656c1256)

Solutions

  1. Find the Relationship whose target is '.' or './' (the message shows it) and point it at the intended part, or remove the dead relationship entry entirely.
  2. If the relationship is vestigial (e.g. an external link wrongly marked internal), delete the <Relationship> element from the .rels file.
  3. Re-save through PowerPoint/LibreOffice to let a conformant writer rebuild the .rels files.
  4. Validate the package with an OOXML validator before feeding it to these scripts.

Example fix

<!-- before -->
<Relationship Id="rId5" Type=".../customXml" Target="."/>

<!-- after: remove or point at a real part -->
<!-- <Relationship ... /> deleted -->
Defensive patterns

Strategy: validation

Validate before calling

import posixpath

def target_resolves_to_part(target: str, source_part: str) -> bool:
    if not target:
        return False
    joined = posixpath.normpath(posixpath.join(posixpath.dirname(source_part), target)) if not target.startswith("/") else posixpath.normpath(target.lstrip("/"))
    return joined not in ("", ".")

Try / catch

try:
    opc_target(target, source_part, target_mode)
except ValueError as e:
    if "resolves to nothing" in str(e):
        drop_relationship()  # dead entry; remove from .rels rather than guess
    else:
        raise

Prevention

When it happens

Trigger: A Relationship element with Target=".", Target="./", or a target that self-cancels like "word/document.xml/.."; occurs while scanning any .rels file during unpack-based operations (thumbnails, cleaning, comment insertion).

Common situations: Hand-edited or machine-generated .rels with placeholder targets; tools that write Target="" variants for relationships they mean to delete; round-tripped files from buggy serializers.

Related errors


AI-assisted analysis of anthropics/skills@f6656c1256 (2026-08-14). Data as JSON: /api/errors/034f2464eb60e840. Report an issue: GitHub.