langchain-ai/deepagents · error · FleetImportError

{name}: symlink entries are not supported

Error message

{name}: symlink entries are not supported

What it means

The library rejects zip entries that are symlinks (external-attr Unix file type `S_IFLNK`). Extracting symlinks from untrusted archives enables link attacks, so Fleet import refuses them outright. The normalized entry name is in the message.

Source

Thrown at libs/talon/deepagents_talon/fleet_import.py:225

def _validated_entries(archive: zipfile.ZipFile) -> dict[str, zipfile.ZipInfo]:
    entries: dict[str, zipfile.ZipInfo] = {}
    total_size = 0
    for info in archive.infolist():
        name = _normalized_zip_name(info.filename)
        if name is None:
            continue
        if _is_unsafe_zip_path(name):
            msg = f"{info.filename}: unsafe zip path"
            raise FleetImportError(msg)
        if _is_symlink(info):
            msg = f"{name}: symlink entries are not supported"
            raise FleetImportError(msg)
        if info.is_dir():
            continue
        _validate_zip_entry_size(name, info)
        if len(entries) >= _MAX_ZIP_ENTRY_COUNT:
            msg = f"{archive.filename}: too many zip entries"
            raise FleetImportError(msg)
        total_size += info.file_size
        if total_size > _MAX_ZIP_UNCOMPRESSED_BYTES:
            msg = f"{archive.filename}: zip uncompressed size exceeds limit"
            raise FleetImportError(msg)
        entries[name] = info
    return entries


def _normalized_zip_name(name: str) -> str | None:
    normalized = name.replace("\\", "/")
    if not normalized or normalized.endswith("/"):
        return None
    return normalized


def _is_unsafe_zip_path(name: str) -> bool:
    posix = PurePosixPath(name)
    windows = PureWindowsPath(name)

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Find the symlink entries (`zi.external_attr >> 16 == 0o120000`) and replace them with real file copies in the export
  2. Recreate the archive without symlink preservation (plain `zip -r` or Python `zipfile` writes)
  3. Check your build/export pipeline flags that keep symlinks (`-y`, `--dereference` differences) and disable them

Example fix

# before (keeps symlinks)
zip -ry fleet.zip AGENTS.md skills
// after
zip -r fleet.zip AGENTS.md skills  # symlinks stored as regular copies or omitted
Defensive patterns

Strategy: validation

Validate before calling

import zipfile

def has_symlink_entries(path):
    with zipfile.ZipFile(path) as z:
        return any(
            (zi.external_attr >> 16) & 0o170000 == 0o120000
            for zi in z.infolist()
        )

Type guard

def is_symlink_entry(info: zipfile.ZipInfo) -> bool:
    return ((info.external_attr >> 16) & 0o170000) == 0o120000

Try / catch

try:
    import_fleet_zip(zip_path, target_dir=target)
except FleetImportError as exc:
    if "symlink entries are not supported" in str(exc):
        print(f"Rebuild archive without symlink: {exc}")
    raise

Prevention

When it happens

Trigger: `import_fleet_zip` encounters an entry whose `ZipInfo.external_attr >> 16` masked with `0o170000` equals `0o120000`, i.e. a symlink stored with Unix attributes.

Common situations: Archives created with `zip -y` or tar-like tooling that preserves symlinks (e.g. `node_modules/.bin/*` symlinks, docs links), macOS `ditto`/Finder zips containing aliases, or reproducible-build pipelines using symlinked files.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/93e4a995d07ca7a7. Report an issue: GitHub.