Is this a client library issue or a product issue?
Client library issue. Two related bugs in google-genai that together cause interaction.output_audio to raise TypeError when using Lyria models (lyria-3-clip-preview, lyria-3-pro-preview) via Vertex AI with ADC credentials.
Environment details
- Programming language: Python
- OS: Linux (Ubuntu / WSL2)
- Language runtime version: Python 3.12
- Package version: google-genai==2.7.0
- Auth mode: Vertex AI with ADC (vertexai=True, project, location="global")
Steps to reproduce
- Set up Vertex AI ADC credentials with location="global" (required for Lyria)
- Call client.interactions.create() with a Lyria model (async client)
- Access interaction.output_audio on the returned object
import asyncio
from google import genai
async def main():
client = genai.Client(vertexai=True, project="YOUR_PROJECT_ID", location="global").aio
interaction = await client.interactions.create(
model="lyria-3-clip-preview",
input="A short upbeat lo-fi hip hop piece with piano.",
)
# Crashes here:
audio = interaction.output_audio
asyncio.run(main())
Error:
File ".../google/genai/_interactions/types/interaction.py", line 281, in output_audio
for step in reversed(self.steps):
TypeError: 'NoneType' object is not reversible
Root cause analysis
Bug 1 - output_audio missing or [] guard (line 281 of interaction.py)
output_text already handles steps=None safely:
# output_text — line 248 ✓
for step in reversed(self.steps or []):
# output_audio — line 281 ✗
for step in reversed(self.steps):
# output_image — line 269 ✗
for step in reversed(self.steps):
output_audio and output_image are missing the or [] guard that output_text already has. A one-line fix in each would make them consistent.
Bug 2 - is_legacy_lyria_response_body doesn't match Vertex AI resource paths
_maybe_coerce_outputs (which converts the legacy outputs field into steps) only triggers when the response body's model field matches:
# _legacy_lyria.py
LEGACY_LYRIA_MODELS = frozenset({"lyria-3-pro-preview", "lyria-3-clip-preview"})
def is_legacy_lyria_response_body(data):
model = typed_data.get("model")
return isinstance(model, str) and model in LEGACY_LYRIA_MODELS
However, the Vertex AI endpoint returns model as a full resource path, e.g.:
projects/5786546123365/locations/global/publishers/google/models/lyria-3-clip-preview
This does not match "lyria-3-clip-preview" exactly, so _maybe_coerce_outputs skips the outputs → steps rewrite. As a result, steps stays None (Pydantic allows it despite the List[Step] annotation) and the outputs field is stored in pydantic_extra instead.
Combined effect: steps=None → output_audio crashes; audio data is accessible but stranded in interaction.model_extra["outputs"].
Expected behavior
interaction.output_audio should return the AudioContent object (or None) without raising TypeError, regardless of whether steps is None.
Suggested fixes
Bug 1 - add or [] to output_audio and output_image (same pattern already used in output_text):
# interaction.py line 281
for step in reversed(self.steps or []): # was: reversed(self.steps)
# interaction.py line 269
for step in reversed(self.steps or []): # was: reversed(self.steps)
Bug 2 - make is_legacy_lyria_response_body match the full resource path variant:
def is_legacy_lyria_response_body(data):
model = typed_data.get("model")
if not isinstance(model, str):
return False
# Match both short name and full Vertex AI resource path
return any(model == m or model.endswith(f"/models/{m}") for m in LEGACY_LYRIA_MODELS)
Workaround (applied in our codebase)
try:
audio = interaction.output_audio
except TypeError:
# steps=None due to Bug 2; fall back to __pydantic_extra__["outputs"]
from google.genai._interactions.types.audio_content import AudioContent as _AudioContent
raw_outputs = (interaction.model_extra or {}).get("outputs") or []
audio = None
for item in reversed(raw_outputs):
if isinstance(item, dict) and item.get("type") == "audio":
audio = _AudioContent.model_validate(item)
break
elif hasattr(item, "type") and item.type == "audio":
audio = item
break
Is this a client library issue or a product issue?
Client library issue. Two related bugs in google-genai that together cause interaction.output_audio to raise TypeError when using Lyria models (lyria-3-clip-preview, lyria-3-pro-preview) via Vertex AI with ADC credentials.
Environment details
Steps to reproduce
Error:
Root cause analysis
Bug 1 - output_audio missing or [] guard (line 281 of interaction.py)
output_text already handles steps=None safely:
output_audio and output_image are missing the or [] guard that output_text already has. A one-line fix in each would make them consistent.
Bug 2 - is_legacy_lyria_response_body doesn't match Vertex AI resource paths
_maybe_coerce_outputs (which converts the legacy outputs field into steps) only triggers when the response body's model field matches:
However, the Vertex AI endpoint returns model as a full resource path, e.g.:
projects/5786546123365/locations/global/publishers/google/models/lyria-3-clip-previewThis does not match "lyria-3-clip-preview" exactly, so _maybe_coerce_outputs skips the outputs → steps rewrite. As a result, steps stays None (Pydantic allows it despite the List[Step] annotation) and the outputs field is stored in pydantic_extra instead.
Combined effect: steps=None → output_audio crashes; audio data is accessible but stranded in interaction.model_extra["outputs"].
Expected behavior
interaction.output_audio should return the AudioContent object (or None) without raising TypeError, regardless of whether steps is None.
Suggested fixes
Bug 1 - add or [] to output_audio and output_image (same pattern already used in output_text):
Bug 2 - make is_legacy_lyria_response_body match the full resource path variant: