BerriAI/litellm · error · Exception

Missing keys= in environment.

Error message

Missing keys={missing_keys} in environment.

What it means

OpenMeterLogger.validate_environment() runs in the callback's __init__ and raises a generic Exception when OPENMETER_API_KEY is absent from the environment. Despite the docstring mentioning OPENMETER_API_ENDPOINT too, only the API key is actually enforced — the endpoint falls back to https://openmeter.cloud. Because this fires at logger construction, adding 'openmeter' to your callbacks list without the env var crashes callback initialization (startup or first import of the callback).

Solutions

  1. Set the API key: export OPENMETER_API_KEY=<your OpenMeter API key>
  2. Optionally set the endpoint if not using OpenMeter Cloud: export OPENMETER_API_ENDPOINT=https://<your-endpoint> (the code appends /api/v1/events, so provide the base URL only)
  3. Confirm the variable is visible to the process that constructs the callback (printenv OPENMETER_API_KEY inside the container/runtime)
  4. Restart/redeploy the proxy or re-import the SDK so the callback reconstructs and validation passes

Example fix

# before
litellm_settings:
  callbacks: ["openmeter"]
# env: nothing set -> Exception at startup

# after
litellm_settings:
  callbacks: ["openmeter"]
# env:
# OPENMETER_API_KEY=<key>
# OPENMETER_API_ENDPOINT=https://openmeter.cloud  # optional
Defensive patterns

Strategy: validation

Validate before calling

import os

if not os.getenv('OPENMETER_API_KEY'):
    raise SystemExit('OPENMETER_API_KEY is required when the openmeter callback is enabled')
# optional: sanity-check a custom endpoint base URL
endpoint = os.getenv('OPENMETER_API_ENDPOINT', 'https://openmeter.cloud')
assert endpoint.startswith('http'), 'OPENMETER_API_ENDPOINT must be a base http(s) URL'

Try / catch

try:
    from litellm.integrations.openmeter import OpenMeterLogger
    cb = OpenMeterLogger()  # validate_environment runs here
except Exception as e:
    raise RuntimeError(f'OpenMeter callback misconfigured: {e}') from e

Prevention

When it happens

Trigger: Adding openmeter to litellm_callbacks / litellm_settings.callbacks in config.yaml (or litellm.callbacks = ['openmeter'] in SDK usage) in a process where OPENMETER_API_KEY is unset. The error message formats the missing key(s) as a Python list, e.g. Missing keys=['OPENMETER_API_KEY'] in environment.

Common situations: Enabling OpenMeter cost logging after reading the docs but only setting the endpoint var; env var set in a local .env that the deployed container never loads; OPENMETER_API_KEY defined in a CI secrets mask but not exported; rotating keys and accidentally deleting the variable; expecting the endpoint to be required too and misreading which var failed.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at litellm/integrations/openmeter.py:49

        super().__init__()
        self.validate_environment()
        self.async_http_handler = get_async_httpx_client(llm_provider=httpxSpecialProvider.LoggingCallback)
        self.sync_http_handler = HTTPHandler()

    def validate_environment(self):
        """
        Expects
        OPENMETER_API_ENDPOINT,
        OPENMETER_API_KEY,

        in the environment
        """
        missing_keys: Final = []
        if os.getenv("OPENMETER_API_KEY", None) is None:
            missing_keys.append("OPENMETER_API_KEY")

        if len(missing_keys) > 0:
            raise Exception(f"Missing keys={missing_keys} in environment.")

    def _common_logic(self, kwargs: dict, response_obj):
        call_id: Final = response_obj.get("id", kwargs.get("litellm_call_id"))
        dt: Final = get_utc_datetime().isoformat()
        cost: Final = kwargs.get("response_cost", None)
        model: Final = kwargs.get("model")
        usage = {}
        if (
            isinstance(response_obj, litellm.ModelResponse) or isinstance(response_obj, litellm.EmbeddingResponse)
        ) and hasattr(response_obj, "usage"):
            usage = {
                "prompt_tokens": response_obj["usage"].get("prompt_tokens", 0),
                "completion_tokens": response_obj["usage"].get("completion_tokens", 0),
                "total_tokens": response_obj["usage"].get("total_tokens"),
            }

        # OPENMETER_TRUST_REQUEST_USER (default "true"): when set to "false",
        # the request-supplied `user` field is ignored and the subject is

View on GitHub (pinned to 77b7c6c40c)