{"record":{"id":"350eaaa831c11bee","repo":"BerriAI/litellm","slug":"invalid-operation-name-format-operation-name-e","errorCode":null,"errorMessage":"Invalid operation name format: {operation_name}. Expected format: projects/PROJECT/locations/LOCATION/publishers/google/models/MODEL/operations/OPERATION_ID","messagePattern":"Invalid operation name format: (.+?)\\. Expected format: projects/PROJECT/locations/LOCATION/publishers/google/models/MODEL/operations/OPERATION_ID","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/vertex_ai/videos/transformation.py","lineNumber":426,"sourceCode":"        return video_obj\n\n    def transform_video_status_retrieve_request(\n        self,\n        video_id: str,\n        api_base: str,\n        litellm_params: GenericLiteLLMParams,\n        headers: dict,\n    ) -> tuple[str, dict]:\n        \"\"\"\n        Transform the video status retrieve request for Veo API.\n\n        Veo polls operations using :fetchPredictOperation endpoint with POST request.\n        \"\"\"\n        operation_name: Final = extract_original_video_id(video_id)\n        model: Final = self.extract_model_from_operation_name(operation_name)\n\n        if not model:\n            raise ValueError(\n                f\"Invalid operation name format: {operation_name}. \"\n                \"Expected format: projects/PROJECT/locations/LOCATION/publishers/google/models/MODEL/operations/OPERATION_ID\"\n            )\n\n        # Construct the full URL including model ID\n        # URL format: https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT/locations/LOCATION/publishers/google/models/MODEL:fetchPredictOperation\n        # Strip trailing slashes from api_base and append model\n        url: Final = f\"{api_base.rstrip('/')}/{model}:fetchPredictOperation\"\n\n        # Request body contains the operation name\n        params: Final = {\"operationName\": operation_name}\n\n        return url, params\n\n    def transform_video_status_retrieve_response(\n        self,\n        raw_response: httpx.Response,\n        logging_obj: LiteLLMLoggingObj,","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/vertex_ai/videos/transformation.py#L408-L444","documentation":"When polling a Veo operation, LiteLLM rebuilds the fetchPredictOperation URL from the stored operation name by splitting it on \"/\" and taking index 7 as the model (`projects/0/P/1? ... publishers/5 google/6 models/7 -> index 7 is MODEL`). If the string has fewer than 8 slash-separated segments, `extract_model_from_operation_name` returns None and this ValueError raises. Practically: the video_id passed to video_status()/content download is not a full Vertex operation name.","triggerScenarios":"Calling litellm.video_status(video_id=...) with a hand-truncated or edited ID (e.g. just the OPERATION_ID tail), an ID from a different provider, or a provider-prefixed ID that was double-encoded/decoded so the operation path was lost.","commonSituations":"Persisting only the short operation ID instead of the full VideoObject.id; string-munging IDs between services; replaying IDs captured from a non-Vertex (e.g. Gemini API) run.","solutions":["Use the exact id returned by the generation call: video = litellm.video_generation(...); litellm.video_status(video_id=video.id) — do not truncate it.","If you store IDs, store the full `projects/.../operations/OP` string (or the provider-encoded VideoObject.id) unchanged.","If you only have OPERATION_ID, reconstruct: f\"projects/{project}/locations/{location}/publishers/google/models/{model}/operations/{op_id}\".","Do not pass IDs obtained from non-Vertex video APIs to the Vertex status route."],"exampleFix":"# before\nlitellm.video_status(video_id=\"5f2d3b4c-...\")  # short op id only -> raises\n\n# after\nresult = litellm.video_generation(model=\"vertex_ai/veo-2.0-generate-001\", prompt=p, vertex_project=proj)\nlitellm.video_status(video_id=result.id)  # full projects/.../operations/... name","handlingStrategy":"type-guard","validationCode":"import re\n\nOPERATION_RE = re.compile(r\"^projects/[^/]+/locations/[^/]+/publishers/[^/]+/models/[^/]+/operations/[^/]+$\")\n\ndef is_full_vertex_operation(video_id: str) -> bool:\n    return bool(OPERATION_RE.match(video_id))","typeGuard":"def is_full_vertex_operation(video_id: str) -> bool:\n    parts = video_id.split(\"/\")\n    return len(parts) >= 8 and parts[0] == \"projects\" and \"operations\" in parts","tryCatchPattern":"try:\n    status = litellm.video_status(video_id=vid, vertex_project=proj)\nexcept ValueError as e:\n    if \"Invalid operation name format\" in str(e):\n        raise ValueError(f\"Stored video_id is truncated: {vid!r}; persist the full operation name\") from e\n    raise","preventionTips":["Persist the untouched VideoObject.id returned by generation; never substring it.","Validate stored IDs against the projects/.../operations/... shape before replaying them.","If you must rebuild, reconstruct the full path from project/location/model/op_id you already know."],"tags":["vertex-ai","veo","operation-id","video-generation","validation"],"backgroundTag":"invalid-operation-id","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}