Repository navigation
Description
Is there an existing issue for this? Searched "fileData", "file_data", "FileData UnknownPart" in firebase/flutterfire. None found. #17615 (Files API support) is related but about sending files, not parsing them.
Which plugins are affected? AI
Which platforms are affected? All (pure Dart parsing in firebase_ai)
Description
parsePart in packages/firebase_ai/firebase_ai/lib/src/content.dart matches every part type by its lowerCamelCase JSON key (functionCall, executableCode, codeExecutionResult, inlineData, text), except file data, which is matched only as snake_case:
// content.dart, firebase_ai 4.0.0 (same on main)
if (jsonObject.containsKey('inlineData')) { ... } // line 157, camelCase
...
case {
'file_data': { // line 178, snake_case
'file_uri': final String fileUri,
'mime_type': final String mimeType,
}
}:
return FileData(mimeType, fileUri, ...);
...
return UnknownPart(jsonObject); // line 189FileData.toJson() also emits snake_case ({'file_data': {'file_uri': ..., 'mime_type': ...}}, line 506). Requests work because the API accepts both the proto field name and the lowerCamelCase form on input. Responses are the problem: the Gemini API serialises Part.fileData as fileData / fileUri / mimeType (see the FileData object in the REST reference, https://ai.google.dev/api/caching#FileData), so a fileData part in a model response never matches the file_data case and falls through to UnknownPart. Callers that switch on FileData to read fileUri never see one; they get an UnknownPart whose data carries the raw map.
Expected: parsePart recognises fileData with fileUri / mimeType (and ideally keeps accepting file_data for compatibility), consistent with how inlineData is handled.
Reproducing the issue
parsePart is not exported, so the shortest reproduction is a canned response through GenerativeModel with a custom http.Client (no Firebase project needed beyond setupFirebaseCoreMocks() from firebase_core_platform_interface/test.dart):
// in a flutter test
final client = _FakeClient(jsonEncode({
'candidates': [
{
'content': {
'role': 'model',
'parts': [
{'fileData': {'fileUri': 'gs://bucket/image.png', 'mimeType': 'image/png'}},
],
},
'finishReason': 'STOP',
}
],
}));
final model = FirebaseAI.googleAI().generativeModel(
model: 'gemini-3.5-flash',
httpClient: client,
);
final response = await model.generateContent([Content.text('hi')]);
final part = response.candidates.first.content.parts.first;
print(part.runtimeType); // UnknownPart, expected FileData
print((part as UnknownPart).data); // {thought: false, fileData: {...}}Changing the canned key to file_data / file_uri / mime_type yields a FileData part, which shows the casing is the only difference.
Firebase Core version: 4.15.0
Flutter Version: 3.47.2 stable
firebase_ai version: 4.0.0 (also reproduced by reading main at the time of filing)
Relevant Log Output: none, parsing silently falls back to UnknownPart.
Additional context and comments
Found while adding response-part handling in the Genkit Dart plugin for Firebase AI Logic; a test there now pins the current behaviour so an upstream fix shows up as a test change. Happy to send a PR: add a 'fileData': {'fileUri': ..., 'mimeType': ...} case alongside the existing file_data case, plus a unit test for both spellings.
Activity
SelaseKay commentedon Oct 11, 2026
Hi @cabljac, thanks for the report. We're looking into it.