BerriAI/litellm · error · ValueError

Remote module loading (s3://, gcs://) is only permitted from

Error message

Remote module loading (s3://, gcs://) is only permitted from the config-file load path. Register the module under ``litellm_settings`` in your config.yaml instead.

What it means

Security guard in get_instance_fn: an s3:// or gcs:// module reference was supplied without config_file_path, i.e. from request-body input rather than the trusted config-file load path. Remote code loading from object storage is only permitted for operator-controlled config.yaml values, so the URL is rejected as untrusted input to prevent arbitrary code loading.

Source

Thrown at litellm/proxy/types_utils/utils.py:23

from collections.abc import Callable
from typing import Any, Final, Literal, get_type_hints


def get_instance_fn(value: str, config_file_path: str | None = None) -> Any:
    module_name = value
    instance_name = None
    try:
        # Check if value starts with s3:// or gcs://
        if value.startswith("s3://") or value.startswith("gcs://"):
            # Remote module loading is a documented operator feature when
            # invoked from config-file load (``config_file_path`` carries
            # the YAML path). Without that signal the URL is request-body
            # data on an admin endpoint — a one-step admin-to-RCE primitive
            # via ``_load_instance_from_remote_storage``'s ``exec_module``.
            # Register the module under ``litellm_settings`` in the
            # config.yaml instead.
            if config_file_path is None:
                raise ValueError(
                    "Remote module loading (s3://, gcs://) is only "
                    "permitted from the config-file load path. Register "
                    "the module under ``litellm_settings`` in your "
                    "config.yaml instead."
                )
            return _load_instance_from_remote_storage(value, config_file_path)

        # Split the path by dots to separate module from instance
        parts: Final = value.split(".")

        # The module path is all but the last part, and the instance_name is the last part
        module_name = ".".join(parts[:-1])
        instance_name = parts[-1]

        module_file_path = None
        if config_file_path is not None:
            directory: Final = os.path.dirname(config_file_path)
            module_file_path = os.path.join(directory, *module_name.split(".")) + ".py"

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Move the remote module reference into litellm_settings in your config.yaml instead of loading it from an arbitrary path.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/proxy/types_utils/utils.py:23 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/67648e0e76101160. Report an issue: GitHub.