{"record":{"id":"dce4090f9bbb7472","repo":"BerriAI/litellm","slug":"invalid-czrn-format-czrn","errorCode":null,"errorMessage":"Invalid CZRN format: {czrn}","messagePattern":"Invalid CZRN format: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/integrations/cloudzero/cz_resource_names.py","lineNumber":111,"sourceCode":"        czrn: Final = f\"czrn:{service_type}:{provider}:{region}:{owner_account_id}:{resource_type}:{cloud_local_id}\"\n\n        if not self.is_valid(czrn):\n            raise ValueError(f\"Generated CZRN is invalid: {czrn}\")\n\n        return czrn\n\n    def is_valid(self, czrn: str) -> bool:\n        \"\"\"Validate a CZRN string against the standard format.\"\"\"\n        return bool(self.CZRN_REGEX.match(czrn))\n\n    def extract_components(self, czrn: str) -> tuple[str, str, str, str, str, str]:\n        \"\"\"Extract all components from a CZRN.\n\n        Returns: (service_type, provider, region, owner_account_id, resource_type, cloud_local_id)\n        \"\"\"\n        match: Final = self.CZRN_REGEX.match(czrn)\n        if not match:\n            raise ValueError(f\"Invalid CZRN format: {czrn}\")\n\n        return cast(tuple[str, str, str, str, str, str], match.groups())\n\n    def _normalize_provider(self, provider: str) -> str:\n        \"\"\"Normalize provider names to standard CZRN format.\"\"\"\n        # Map common provider names to CZRN standards\n        provider_map: Final = {\n            litellm.LlmProviders.AZURE.value: \"azure\",\n            litellm.LlmProviders.AZURE_AI.value: \"azure\",\n            litellm.LlmProviders.ANTHROPIC.value: \"anthropic\",\n            litellm.LlmProviders.BEDROCK.value: \"aws\",\n            litellm.LlmProviders.VERTEX_AI.value: \"gcp\",\n            litellm.LlmProviders.GEMINI.value: \"google\",\n            litellm.LlmProviders.COHERE.value: \"cohere\",\n            litellm.LlmProviders.HUGGINGFACE.value: \"huggingface\",\n            litellm.LlmProviders.REPLICATE.value: \"replicate\",\n            litellm.LlmProviders.TOGETHER_AI.value: \"together-ai\",\n        }","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/cloudzero/cz_resource_names.py#L93-L129","documentation":"ValueError raised by CZRNGenerator.extract_components when the input string does not match the CZRN regex — fewer than six colon-separated components after 'czrn:', empty components (double colons), uppercase letters in the lowercase-only groups (service_type, region, owner_account_id, resource_type), or a missing/misspelled 'czrn:' prefix. This validates externally supplied strings; use is_valid() first to check without raising.","triggerScenarios":"Calling extract_components on a hand-built or persisted CZRN that was never produced by create_from_components: 'czrn:litellm:openai::cross-region:...' (empty component), 'CZRN:litellm:...' (prefix), 'czrn:litellm:openai:Cross-Region:...' (uppercase region), a truncated string, or leading/trailing whitespace around the czrn.","commonSituations":"CZRNs written by other tooling or edited by hand; strings loaded from config/database without normalization; copy-paste truncation; case-changing transformations (e.g. upper-casing identifiers) applied downstream.","solutions":["Pre-check with generator.is_valid(czrn) — it returns bool instead of raising","Only construct CZRNs via create_from_components / create_from_litellm_data so the format holds by construction","Strip whitespace and lowercase the string before validation if the source is untrusted","If parsing persisted CZRNs, re-generate from the original row data instead of string-munging old values"],"exampleFix":"# before\nsvc, prov, region, owner, rtype, local_id = gen.extract_components(user_supplied_czrn)\n\n# after\nif not gen.is_valid(user_supplied_czrn.strip().lower()):\n    raise ValueError(f\"not a usable CZRN: {user_supplied_czrn!r}\")\nsvc, prov, region, owner, rtype, local_id = gen.extract_components(user_supplied_czrn.strip().lower())","handlingStrategy":"type-guard","validationCode":"czrn = czrn.strip().lower()\nif not generator.is_valid(czrn):\n    raise ValueError(f\"refusing to parse malformed CZRN: {czrn!r}\")","typeGuard":"import re\n\nCZRN_PATTERN = re.compile(r\"^czrn:([a-z0-9-]+):([a-zA-Z0-9-]+):([a-z0-9-]+):([a-z0-9-]+):([a-z0-9-]+):(.+)$\")\n\ndef is_czrn(value: str) -> bool:\n    return isinstance(value, str) and bool(CZRN_PATTERN.match(value))","tryCatchPattern":"try:\n    components = generator.extract_components(czrn)\nexcept ValueError:\n    # regenerate from source data instead of repairing the string\n    components = None","preventionTips":["Always gate extract_components with generator.is_valid()","Generate CZRNs only through create_from_components — never string-format them by hand","Avoid case-transforming persisted CZRNs downstream (several components are lowercase-only)"],"tags":["cloudzero","czrn","identifier-validation","parsing"],"backgroundTag":"resource-id-validation-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}