langchain-ai/deepagents · error · ChannelMediaError

str(exc) (re-raised from resolve_bounded_media_path)

Error message

str(exc) (re-raised from resolve_bounded_media_path)

What it means

`validate_media` wraps failures from `resolve_bounded_media_path` (path escaping the media root, oversized, or invalid path) by re-raising them as `ChannelMediaError` (a ValueError subclass) with the original message. This gives channel adapters a single exception type for unsafe media paths.

Source

Thrown at libs/talon/deepagents_talon/channels/base.py:263

        root: Optional directory that must contain the media after symlink
            resolution.
        max_bytes: Optional global media size cap.

    Returns:
        The validated media payload.

    Raises:
        ChannelMediaError: If the file is missing, unsupported, or too large.
    """
    try:
        path = (
            resolve_bounded_media_path(media.path, root, require_relative=False)
            if root is not None
            else media.path.expanduser()
        )
    except ValueError as exc:
        msg = str(exc)
        raise ChannelMediaError(msg) from exc
    if not path.is_file():
        msg = f"media file does not exist: {path}"
        raise ChannelMediaError(msg)

    detected = _media_type(path)
    if detected != media.media_type:
        msg = f"media file type {detected!r} does not match requested type {media.media_type!r}"
        raise ChannelMediaError(msg)

    return _validate_media_size(media, path=path, max_bytes=max_bytes)


def message_with_media_paths(
    message: ChannelMessage,
    *,
    media_paths: Sequence[str],
    mime_types: Sequence[str] = (),
    has_media: bool | None = None,

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Read the embedded message from `resolve_bounded_media_path` and fix the path accordingly.
  2. Place the file inside the configured media root and use a path relative to it.
  3. Clear/adjust the media root env (`DEEPAGENTS_TALON_OUTBOUND_MEDIA_DIR` or workspace) if the restriction is unintended.
  4. Catch `ChannelMediaError` in the adapter and report it to the user instead of crashing.

Example fix

# before
validate_media(ChannelMedia(path=Path('/etc/passwd'), media_type='image'))

# after
validate_media(ChannelMedia(path=Path('outbound/logo.png').relative_to(media_root), media_type='image'))
Defensive patterns

Strategy: try-catch

Validate before calling

from deepagents_talon.media import resolve_bounded_media_path
try:
    resolve_bounded_media_path(media.path, root, require_relative=False)
except ValueError:
    ...  # reject before calling send_media

Try / catch

try:
    await channel.send_media(media)
except ChannelMediaError as exc:
    logger.warning('media path rejected: %s', exc)
    await channel.send_text(f'Could not send attachment: {exc}')

Prevention

When it happens

Trigger: Calling `validate_media` (directly or via a channel's `send_media`) with a media path that `resolve_bounded_media_path` rejects: absolute path where relative is required, path traversal outside the configured root, or other ValueError raised by the resolver.

Common situations: Passing an absolute path to outbound media when `DEEPAGENTS_TALON_OUTBOUND_MEDIA_DIR` is set; paths containing `..` escaping the workspace; symlinked paths resolving outside the root.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


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