{"record":{"id":"65d2910fb4703e7e","repo":"BerriAI/litellm","slug":"otel-attributes-must-be-a-mapping-with-optional-i","errorCode":null,"errorMessage":"otel.attributes must be a mapping with optional 'include_list' / 'exclude_list', got {type(value).__name__}","messagePattern":"otel\\.attributes must be a mapping with optional 'include_list' / 'exclude_list', got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/integrations/opentelemetry.py","lineNumber":161,"sourceCode":"        \"gen_ai.request.model\",\n        \"gen_ai.framework\",\n        \"hidden_params\",\n    )\n    + tuple(f\"metadata.{key}\" for key in METRIC_METADATA_KEYS)\n)\n\n\n@dataclass(frozen=True)\nclass OTELMetricAttributeFilter:\n    include_list: list[str] | None = None\n    exclude_list: list[str] | None = None\n\n\ndef _build_metric_attribute_filter(value: Any) -> OTELMetricAttributeFilter:\n    if isinstance(value, OTELMetricAttributeFilter):\n        return value\n    if not isinstance(value, dict):\n        raise ValueError(\n            \"otel.attributes must be a mapping with optional 'include_list' / \"\n            f\"'exclude_list', got {type(value).__name__}\"\n        )\n    return OTELMetricAttributeFilter(\n        include_list=value.get(\"include_list\"),\n        exclude_list=value.get(\"exclude_list\"),\n    )\n\n\ndef _resolve_metric_attribute_filter(\n    attributes: OTELMetricAttributeFilter | None,\n) -> tuple[frozenset[str] | None, frozenset[str] | None]:\n    if attributes is None:\n        return None, None\n    include: Final = attributes.include_list or None\n    exclude: Final = attributes.exclude_list or None\n    if include and exclude:\n        raise ValueError(\"otel.attributes: include_list and exclude_list are mutually exclusive\")","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/integrations/opentelemetry.py#L143-L179","documentation":"LiteLLM's OpenTelemetry metric attribute filter is configured via 'otel.attributes', which must be a mapping (dict) optionally containing include_list/exclude_list. _build_metric_attribute_filter accepts an already-built OTELMetricAttributeFilter or a dict; any other type (str, list, tuple, or a bad YAML parse) raises ValueError naming the offending type.","triggerScenarios":"Writing 'otel.attributes: include_list' (a bare string) in proxy YAML; passing a list of names like 'otel.attributes: [model, endpoint]'; YAML indentation that parses attributes into a scalar instead of a mapping.","commonSituations":"Configuring Prometheus/OpenTelemetry metric label filtering in litellm proxy config.yaml; authors assuming a comma-separated string or flat list is accepted; YAML indentation mistakes nesting the keys under the wrong parent.","solutions":["Use a mapping: otel: attributes: {include_list: [model, api_provider]} (or exclude_list)","Check YAML indentation so 'attributes:' is a key under 'otel:' with list values beneath it","Do not pass a string or list directly as the attributes value","After fixing, restart the proxy; config is parsed at startup so a stale config file will keep failing"],"exampleFix":"# before (config.yaml)\notel:\n  attributes: model,api_provider  # ValueError: ...got str\n\n# after\notel:\n  attributes:\n    include_list:\n      - model\n      - api_provider","handlingStrategy":"type-guard","validationCode":"def valid_otel_attributes(cfg: object) -> bool:\n    return cfg is None or isinstance(cfg, dict) or hasattr(cfg, \"include_list\")","typeGuard":"from typing import Any\n\ndef is_otel_attributes_mapping(value: Any) -> bool:\n    return isinstance(value, dict) and set(value) <= {\"include_list\", \"exclude_list\"}","tryCatchPattern":null,"preventionTips":["Lint proxy config.yaml against a schema before deploying","Use structured config validation for nested tool config like otel.attributes"],"tags":["python","opentelemetry","configuration","yaml","validation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}