iflytek/astron-agent · error · RuntimeError

Sandbox runtime configuration is unavailable

Error message

Sandbox runtime configuration is unavailable

What it means

_load_runtime_config_url validates SKILL_SANDBOX_RUNTIME_CONFIG_URL with the same strict rules as the artifact upload URL but for the runtime-config path: scheme http/https, hostname present, no userinfo, path exactly '/skill-sandbox/internal-runtime-config', no query/fragment, <= 2048 chars, no control chars, valid port. Violations become RuntimeError('Sandbox runtime configuration is unavailable'), raised when _fetch_e2b_runtime_config runs.

Solutions

  1. Set SKILL_SANDBOX_RUNTIME_CONFIG_URL to the exact URL ending in /skill-sandbox/internal-runtime-config, e.g. https://sandbox.example.com/skill-sandbox/internal-runtime-config
  2. Remove query strings, fragments, credentials, or control characters and keep total length <= 2048
  3. Check docker-compose/helm values so the variable is actually substituted (not left as an empty string) at deploy time
  4. Confirm the path against the deployed sandbox runtime-config service version

Example fix

// before
SKILL_SANDBOX_RUNTIME_CONFIG_URL=https://sandbox.example.com

// after
SKILL_SANDBOX_RUNTIME_CONFIG_URL=https://sandbox.example.com/skill-sandbox/internal-runtime-config
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlsplit

RUNTIME_CONFIG_PATH = "/skill-sandbox/internal-runtime-config"

def runtime_config_url_ok() -> bool:
    url = (os.getenv("SKILL_SANDBOX_RUNTIME_CONFIG_URL") or "").strip()
    if not url or len(url) > 2048 or any(c in url for c in "\r\n\t"):
        return False
    p = urlsplit(url)
    try:
        p.port
    except ValueError:
        return False
    return (
        p.scheme in ("http", "https")
        and bool(p.hostname)
        and p.username is None
        and p.password is None
        and p.path == RUNTIME_CONFIG_PATH
        and not p.query
        and not p.fragment
    )

Type guard

from urllib.parse import urlsplit

def is_valid_runtime_config_url(url: object) -> bool:
    if not isinstance(url, str) or not url:
        return False
    p = urlsplit(url)
    return p.scheme in ("http", "https") and bool(p.hostname) and p.path == "/skill-sandbox/internal-runtime-config"

Try / catch

try:
    config = await _fetch_e2b_runtime_config()
except RuntimeError as exc:
    if "Sandbox runtime configuration" in str(exc):
        raise ConfigError(
            "SKILL_SANDBOX_RUNTIME_CONFIG_URL missing/malformed; must end in "
            "/skill-sandbox/internal-runtime-config"
        ) from exc
    raise

Prevention

When it happens

Trigger: _fetch_e2b_runtime_config invoked (sandbox script execution path) while SKILL_SANDBOX_RUNTIME_CONFIG_URL is unset/empty, points to the wrong path (not /skill-sandbox/internal-runtime-config), uses a non-http(s) scheme, contains credentials/query/fragment/control characters, exceeds 2048 chars, or has an invalid port — converted at line 216.

Common situations: E2B sandbox configured with a token/URL pair for a different endpoint version; operator set the root URL without the internal-runtime-config path; the runtime-config service was moved behind a gateway that appends a path prefix; empty env var after a broken docker-compose variable substitution (`${VAR}` left blank).

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/4fc82f640a01f1be. Report an issue: GitHub.

Appendix: source

Thrown at core/agent/service/plugin/skill_sandbox.py:216

    runtime_config_url = (os.getenv(RUNTIME_CONFIG_URL_ENV) or "").strip()
    try:
        parsed = urlsplit(runtime_config_url)
        if (
            not runtime_config_url
            or len(runtime_config_url) > 2048
            or any(char in runtime_config_url for char in ("\r", "\n", "\t"))
            or parsed.scheme not in {"http", "https"}
            or not parsed.hostname
            or parsed.username is not None
            or parsed.password is not None
            or parsed.path != RUNTIME_CONFIG_PATH
            or bool(parsed.query)
            or bool(parsed.fragment)
        ):
            raise ValueError
        parsed.port
    except (TypeError, ValueError):
        raise RuntimeError(SANDBOX_RUNTIME_CONFIG_ERROR) from None
    return runtime_config_url


def _load_runtime_credential_token() -> str:
    token = (os.getenv(RUNTIME_CREDENTIAL_TOKEN_ENV) or "").strip()
    if not token:
        token_file = (os.getenv(RUNTIME_CREDENTIAL_TOKEN_FILE_ENV) or "").strip()
        if token_file:
            try:
                token = Path(token_file).read_text(encoding="utf-8").strip()
            except (OSError, UnicodeError):
                raise RuntimeError(SANDBOX_RUNTIME_CONFIG_ERROR) from None
    if (
        len(token) < MIN_RUNTIME_CREDENTIAL_TOKEN_LENGTH
        or "\r" in token
        or "\n" in token
    ):
        raise RuntimeError(SANDBOX_RUNTIME_CONFIG_ERROR)

View on GitHub (pinned to 5e758547a8)