BerriAI/litellm · error · ValueError

integration_token must be provided for Vantage destination…

Error message

integration_token must be provided for Vantage destination (set VANTAGE_INTEGRATION_TOKEN env var or pass in destination_config)

What it means

FocusVantageDestination.__init__ raises this ValueError after the api_key check passes but the config dict has no integration_token. The Vantage destination needs two credentials: an api_key (VANTAGE_API_KEY) and an integration_token (VANTAGE_INTEGRATION_TOKEN). The factory resolves the token from overrides or the VANTAGE_INTEGRATION_TOKEN environment variable.

Solutions

  1. Export VANTAGE_INTEGRATION_TOKEN alongside VANTAGE_API_KEY in the proxy environment.
  2. Pass integration_token in destination_config: {'api_key': '...', 'integration_token': '...'}.
  3. Fetch the integration token from your Vantage account (cost-import/integration settings) if you only generated the API key.
  4. Verify neither value is an empty string before starting the proxy.

Example fix

# before
destination_config = {'api_key': 'vt_...'}  # missing token -> ValueError

# after
destination_config = {'api_key': 'vt_...', 'integration_token': 'it_...'}
Defensive patterns

Strategy: validation

Validate before calling

import os

token = overrides.get('integration_token') or os.getenv('VANTAGE_INTEGRATION_TOKEN')
if not token:
    raise SystemExit('VANTAGE_INTEGRATION_TOKEN (or integration_token override) is required for Vantage FOCUS exports')

Type guard

def has_vantage_credentials(config: dict) -> bool:
    return all([
        config.get('api_key') or os.getenv('VANTAGE_API_KEY'),
        config.get('integration_token') or os.getenv('VANTAGE_INTEGRATION_TOKEN'),
    ])

Prevention

When it happens

Trigger: Configuring a 'vantage' FOCUS destination with VANTAGE_API_KEY set but VANTAGE_INTEGRATION_TOKEN unset; passing only api_key in destination_config; a deployment where only one of the two secrets was added to the secret store.

Common situations: Following a tutorial that only mentions the API key; the integration token is a separate value generated in the Vantage UI for cost-import integrations, so it's commonly overlooked; partial secret rotation leaves only one credential set.

Related errors


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

Appendix: source

Thrown at litellm/integrations/focus/destinations/vantage_destination.py:108

class FocusVantageDestination(FocusDestination):
    """Upload FOCUS CSV exports to the Vantage cost-import API."""

    def __init__(
        self,
        *,
        prefix: str,
        config: dict[str, Any] | None = None,
    ) -> None:
        config = config or {}
        api_key: Final = config.get("api_key")
        integration_token: Final = config.get("integration_token")
        if not api_key:
            raise ValueError(
                "api_key must be provided for Vantage destination "
                "(set VANTAGE_API_KEY env var or pass in destination_config)"
            )
        if not integration_token:
            raise ValueError(
                "integration_token must be provided for Vantage destination "
                "(set VANTAGE_INTEGRATION_TOKEN env var or pass in destination_config)"
            )
        self.api_key = api_key
        self.integration_token = integration_token
        self.base_url = config.get("base_url", "https://api.vantage.sh")
        self.prefix = prefix

    async def deliver(
        self,
        *,
        content: bytes,
        time_window: FocusTimeWindow,
        filename: str,
    ) -> None:
        """Upload CSV content to the Vantage API, batching if needed."""
        if not content:
            verbose_logger.debug("Vantage destination: empty content, skipping upload")

View on GitHub (pinned to 77b7c6c40c)