{"record":{"id":"bc8d65008ebfe486","repo":"microsoft/semantic-kernel","slug":"audio-content-uri-is-empty","errorCode":null,"errorMessage":"Audio content URI is empty.","messagePattern":"Audio content URI is empty\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"info","filePath":"dotnet/src/Connectors/Connectors.Google/Core/Gemini/Models/GeminiRequest.cs","lineNumber":375,"sourceCode":"        {\n            return new GeminiPart\n            {\n                InlineData = new GeminiPart.InlineDataPart\n                {\n                    MimeType = GetMimeTypeFromAudioContent(audioContent),\n                    InlineData = Convert.ToBase64String(audioContent.Data.Value.ToArray())\n                }\n            };\n        }\n\n        if (audioContent.Uri is not null)\n        {\n            return new GeminiPart\n            {\n                FileData = new GeminiPart.FileDataPart\n                {\n                    MimeType = GetMimeTypeFromAudioContent(audioContent),\n                    FileUri = audioContent.Uri ?? throw new InvalidOperationException(\"Audio content URI is empty.\")\n                }\n            };\n        }\n\n        throw new InvalidOperationException(\"Audio content does not contain any data or uri.\");\n    }\n\n    private static string GetMimeTypeFromAudioContent(AudioContent audioContent)\n    {\n        return audioContent.MimeType\n               ?? throw new InvalidOperationException(\"Audio content MimeType is empty.\");\n    }\n\n    private static GeminiPart CreateGeminiPartFromBinary(BinaryContent binaryContent)\n    {\n        // Binary data takes precedence over URI.\n        if (binaryContent.Data is { IsEmpty: false })\n        {","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Connectors/Connectors.Google/Core/Gemini/Models/GeminiRequest.cs#L357-L393","documentation":"Thrown by CreateGeminiPartFromAudio when building a Gemini FileDataPart for an AudioContent that has a URI. The expression audioContent.Uri ?? throw guards against a null URI. In practice this throw is unreachable because it sits inside an 'if (audioContent.Uri is not null)' block, so the value was just proven non-null; it is defensive code to satisfy nullable reference analysis and protect against concurrent mutation of the content object.","triggerScenarios":"Only fires if audioContent.Uri is reassigned to null between the 'is not null' check (line 368) and the FileUri assignment (line 375) — i.e. a race condition where another thread mutates the same AudioContent instance during request serialization.","commonSituations":"Sharing a single AudioContent instance across threads/tasks while one thread serializes a Gemini request and another clears or replaces the Uri. Effectively never hit in single-threaded usage.","solutions":["Do not mutate an AudioContent instance concurrently with serializing it; treat content objects as effectively immutable once handed to the kernel.","If you are seeing this in production, audit for code that reuses/clears the same AudioContent across parallel requests.","Supply a copy of the content or a freshly constructed AudioContent per request."],"exampleFix":"// before (shared mutable content)\nvar audio = new AudioContent(...);\n// task A: kernel.InvokeAsync(... audio ...)  // serializes\n// task B: audio.Uri = null;                  // mutates during serialize\n\n// after (one immutable content per request)\nvar audio = new AudioContent(uri: myUri, mimeType: \"audio/wav\");\nawait kernel.InvokeAsync(... audio ...);","handlingStrategy":"validation","validationCode":"// Validate AudioContent immutability before invoking\nstatic bool IsAudioContentSafe(AudioContent c)\n    => c.Uri is not null && !string.IsNullOrEmpty(c.MimeType);\n// Then ensure no concurrent mutation of c.Uri occurs during the call.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat AudioContent (and all content objects) as immutable once passed to the kernel.","Never share a content instance across parallel invocations that mutate it.","Construct a fresh AudioContent per request rather than reusing/clearing one."],"tags":["gemini","audio","unreachable","concurrency"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}