BerriAI/litellm · error · ValueError

Invalid ARN format

Error message

Invalid ARN format: {arn}

What it means

_extract_region_from_arn splits the AgentCore ARN on ':' and requires at least 4 parts so that parts[3] (the region) exists. This ValueError is raised when the value after 'agentcore/' is a truncated ARN or a bare runtime identifier — e.g. 'arn:aws:bedrock-agentcore' (3 parts) or 'my-runtime-id' (1 part). It is the second format gate after the prefix check.

Solutions

  1. Pass the full runtime ARN after the prefix: agentcore/arn:aws:bedrock-agentcore:region:account:runtime/runtime-id
  2. Validate the ARN has at least 6 colon-separated fields and starts with arn:aws:bedrock-agentcore: before calling litellm
  3. Check env/YAML templates for empty region or account substitutions that silently shrink the ARN

Example fix

// before
model = "agentcore/hosted_agent_r9jvp-3ySZuRHjLC"  // bare runtime id

// after
model = "agentcore/arn:aws:bedrock-agentcore:us-west-2:888602223428:runtime/hosted_agent_r9jvp-3ySZuRHjLC"
Defensive patterns

Strategy: validation

Validate before calling

def assert_full_agentcore_arn(model: str) -> None:
    arn = model.split("/", 1)[1] if model.startswith("agentcore/") else model
    parts = arn.split(":")
    if len(parts) < 6 or not parts[3]:
        raise ValueError(f"Not a full AgentCore runtime ARN (need >=6 colon fields): {arn!r}")

assert_full_agentcore_arn(model)
resp = litellm.completion(model=model, messages=msgs)

Type guard

def is_full_agentcore_arn(arn: str) -> bool:
    """True when arn has a region field and the full 6+ part structure."""
    parts = arn.split(":")
    return len(parts) >= 6 and bool(parts[3])

Try / catch

try:
    resp = litellm.completion(model=model, messages=msgs)
except ValueError as e:
    if "Invalid ARN format" in str(e):
        raise ConfigError(f"AgentCore model must carry the full runtime ARN: {model!r}") from e
    raise

Prevention

When it happens

Trigger: model="agentcore/hosted_agent_xyz" (bare runtime id instead of the ARN); an ARN copy-pasted but truncated at the account or service field; CI/CD or env-var interpolation that drops the colon-separated fields; a template with empty {region} that collapses the ARN.

Common situations: Using the friendly runtime name shown in the console list view instead of its ARN; long ARNs mangled by YAML folding or shell truncation; building ARNs from templates whose region/account variables are empty.

Related errors


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

Appendix: source

Thrown at litellm/llms/bedrock/chat/agentcore/transformation.py:177

        returns: "arn:aws:bedrock-agentcore:us-west-2:888602223428:runtime/hosted_agent_r9jvp-3ySZuRHjLC"
        """
        parts: Final = model.split("/", 1)
        if len(parts) != 2 or parts[0] != "agentcore":
            raise ValueError(
                "Invalid model format. Expected format: 'model=bedrock/agentcore/arn:aws:bedrock-agentcore:region:account:runtime/runtime_id'"
            )
        return parts[1]

    def _extract_region_from_arn(self, arn: str) -> str:
        """
        Extract region from ARN
        arn:aws:bedrock-agentcore:us-west-2:888602223428:runtime/hosted_agent_r9jvp-3ySZuRHjLC
        returns: us-west-2
        """
        parts: Final = arn.split(":")
        if len(parts) >= 4:
            return parts[3]
        raise ValueError(f"Invalid ARN format: {arn}")

    def _get_runtime_session_id(self, optional_params: dict) -> str:
        """
        Get or generate runtime session ID (must be 33+ chars)
        """
        session_id: Final = optional_params.get("runtimeSessionId", None)
        if session_id:
            verbose_logger.debug("Using provided runtimeSessionId: %s", session_id)
            return session_id

        # Generate a session ID with 33+ characters
        generated_id: Final = f"litellm-session-{uuid.uuid4()}"
        verbose_logger.debug("Generated new session ID: %s", generated_id)
        return generated_id

    def _get_runtime_user_id(self, optional_params: dict) -> str | None:
        """
        Get runtime user ID if provided

View on GitHub (pinned to 77b7c6c40c)