microsoft/semantic-kernel · error · ServiceInvalidRequestError

Audio content uri must be a string to a local file.

Error message

Audio content uri must be a string to a local file.

What it means

Raised by OpenAIAudioToTextBase.get_text_contents — a ServiceInvalidRequestError (not ServiceInitializationError). The OpenAI audio transcription API uploads a local file, so audio_content.uri must be a plain Python str pointing to a file on disk. If uri is any other type (pathlib.Path, HttpUrl, bytes, None, or a pydantic Url object), this check fails. This is a runtime error during transcription, not during service construction.

Source

Thrown at python/semantic_kernel/connectors/ai/open_ai/services/open_ai_audio_to_text_base.py:46

    async def get_text_contents(
        self,
        audio_content: AudioContent,
        settings: PromptExecutionSettings | None = None,
        **kwargs: Any,
    ) -> list[TextContent]:
        if not settings:
            settings = OpenAIAudioToTextExecutionSettings(ai_model_id=self.ai_model_id)
        else:
            if not isinstance(settings, OpenAIAudioToTextExecutionSettings):
                settings = self.get_prompt_execution_settings_from_settings(settings)

        assert isinstance(settings, OpenAIAudioToTextExecutionSettings)  # nosec

        if settings.ai_model_id is None:
            settings.ai_model_id = self.ai_model_id

        if not isinstance(audio_content.uri, str):
            raise ServiceInvalidRequestError("Audio content uri must be a string to a local file.")

        settings.filename = audio_content.uri

        response = await self._send_request(settings)
        assert isinstance(response, Transcription)  # nosec

        return [
            TextContent(
                ai_model_id=settings.ai_model_id,
                text=response.text,
                inner_content=response,
            )
        ]

    def get_prompt_execution_settings_class(self) -> type[PromptExecutionSettings]:
        """Get the request settings class."""
        return OpenAIAudioToTextExecutionSettings

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Ensure audio_content.uri is a str: convert pathlib.Path with str(path) before creating AudioContent.
  2. If the audio is remote, download it to a local temp file first, then create AudioContent with the local path.
  3. Check isinstance(audio_content.uri, str) before calling get_text_contents.
  4. Use AudioContent.from_file(path) or set uri=str(local_path) explicitly.

Example fix

# before (pathlib.Path object as uri)
from pathlib import Path
from semantic_kernel.contents import AudioContent

audio = AudioContent(uri=Path('/data/audio.mp3'))
result = await service.get_text_contents(audio)

# after (convert to str)
audio = AudioContent(uri=str(Path('/data/audio.mp3')))
result = await service.get_text_contents(audio)
Defensive patterns

Strategy: type-guard

Validate before calling

from pathlib import Path
from semantic_kernel.contents import AudioContent

def create_audio_content_for_transcription(file_path: str | Path) -> AudioContent:
    """Ensure uri is a str for the OpenAI audio transcription endpoint."""
    if isinstance(file_path, Path):
        file_path = str(file_path)
    if not isinstance(file_path, str):
        raise TypeError(f'Audio file path must be str or Path, got {type(file_path).__name__}')
    return AudioContent(uri=file_path)

Type guard

from semantic_kernel.contents import AudioContent

def is_valid_audio_content_for_transcription(audio_content: AudioContent) -> bool:
    """The OpenAI audio transcription API requires a local file path (str) as uri."""
    return isinstance(audio_content.uri, str)

Try / catch

from semantic_kernel.exceptions.service_exceptions import ServiceInvalidRequestError

try:
    result = await service.get_text_contents(audio_content)
except ServiceInvalidRequestError as e:
    if 'uri must be a string' in str(e):
        # Convert the uri to str and retry, or download remote audio to a local file
        if hasattr(audio_content.uri, '__fspath__'):  # pathlib.Path
            audio_content.uri = str(audio_content.uri)
            result = await service.get_text_contents(audio_content)
        else:
            raise TypeError('Download remote audio to a local file first') from e
    raise

Prevention

When it happens

Trigger: Calling service.get_text_contents(audio_content) where audio_content.uri is not a str — e.g. a pathlib.Path object, a pydantic HttpsUrl/Url instance, a remote HTTPS URL object, or None. The OpenAI Whisper API requires a local file path to open and upload via multipart form data.

Common situations: Creating AudioContent from a pathlib.Path without converting to str; passing an AudioContent whose data was loaded from a remote URL (uri is an HttpUrl object); using AudioContent.from_bytes() where uri is not set or is a data URI; forgetting that the OpenAI audio endpoint requires a local file, not a URL.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/131f0d3cb4ea6723. Report an issue: GitHub.