-
-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Closed
Labels
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?Have you validated the input using an OpenAPI validator (example)?Have you tested with the latest master to confirm the issue still exists?Have you searched for related issues/PRs?What's the actual output vs expected output?[Optional] Sponsorship to speed up the bug fix or feature request (example)To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
Description
When generating a Get request with content-type application/octet-stream
or text/event-stream
the output returns a MultipartFile
instead of the expected Stream<Uint8List>
.
The generated code then calls the deserialize
which fails with the exception Cannot deserialize
.
I expect the generated method to return Stream<Uint8List>
.
openapi-generator version
openapi-generator-cli 7.12.0-SNAPSHOT
OpenAPI declaration file content or url
ymal schema:
/api/open-ai/session/{id}:
get:
operationId: open_ai_session_retrieve
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
- in: path
name: message_id
schema:
type: string
format: uuid
required: true
tags:
- open-ai
security:
- cookieAuth: []
responses:
'200':
content:
application/octet-stream:
schema:
type: string
format: binary
description: ''
Output:
/// openAiChatSessionMessageRetrieve
///
///
/// Parameters:
/// * [id]
/// * [messageId]
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
/// * [headers] - Can be used to add additional headers to the request
/// * [extras] - Can be used to add flags to the request
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
///
/// Returns a [Future] containing a [Response] with a [MultipartFile] as data
/// Throws [DioException] if API call or serialization fails
Future<Response<MultipartFile>> openAiChatSessionMessageRetrieve({
required String id,
CancelToken? cancelToken,
Map<String, dynamic>? headers,
Map<String, dynamic>? extra,
ValidateStatus? validateStatus,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
final _path = r'/api/open-ai/session/{id}/'
.replaceAll('{' r'id' '}', id.toString())
final _options = Options(
method: r'GET',
responseType: ResponseType.bytes,
headers: <String, dynamic>{
...?headers,
},
extra: <String, dynamic>{
...?extra,
},
validateStatus: validateStatus,
);
final _response = await _dio.request<Object>(
_path,
options: _options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
MultipartFile? _responseData;
try {
final rawData = _response.data;
_responseData = rawData == null
? null
: deserialize<MultipartFile, MultipartFile>(rawData, 'MultipartFile',
growable: true); // CRASH ---> deserialize cannot create MultipartFile
} catch (error, stackTrace) {
throw DioException(
requestOptions: _response.requestOptions,
response: _response,
type: DioExceptionType.unknown,
error: error,
stackTrace: stackTrace,
);
}
return Response<MultipartFile>(
data: _responseData,
headers: _response.headers,
isRedirect: _response.isRedirect,
requestOptions: _response.requestOptions,
redirects: _response.redirects,
statusCode: _response.statusCode,
statusMessage: _response.statusMessage,
extra: _response.extra,
);
}
deserializer:
final _regList = RegExp(r'^List<(.*)>$');
final _regSet = RegExp(r'^Set<(.*)>$');
final _regMap = RegExp(r'^Map<String,(.*)>$');
ReturnType deserialize<ReturnType, BaseType>(dynamic value, String targetType,
{bool growable = true}) {
switch (targetType) {
case 'String':
return '$value' as ReturnType;
case 'int':
return (value is int ? value : int.parse('$value')) as ReturnType;
case 'bool':
if (value is bool) {
return value as ReturnType;
}
final valueString = '$value'.toLowerCase();
return (valueString == 'true' || valueString == '1') as ReturnType;
case 'double':
return (value is double ? value : double.parse('$value')) as ReturnType;
// Rest of models, but no MultipartFile
default:
RegExpMatch? match;
if (value is List && (match = _regList.firstMatch(targetType)) != null) {
targetType = match![1]!; // ignore: parameter_assignments
return value
.map<BaseType>((dynamic v) => deserialize<BaseType, BaseType>(
v, targetType,
growable: growable))
.toList(growable: growable) as ReturnType;
}
if (value is Set && (match = _regSet.firstMatch(targetType)) != null) {
targetType = match![1]!; // ignore: parameter_assignments
return value
.map<BaseType>((dynamic v) => deserialize<BaseType, BaseType>(
v, targetType,
growable: growable))
.toSet() as ReturnType;
}
if (value is Map && (match = _regMap.firstMatch(targetType)) != null) {
targetType = match![1]!.trim(); // ignore: parameter_assignments
return Map<String, BaseType>.fromIterables(
value.keys as Iterable<String>,
value.values.map((dynamic v) => deserialize<BaseType, BaseType>(
v, targetType,
growable: growable)),
) as ReturnType;
}
break;
}
throw Exception('Cannot deserialize');
}
Generation Details
open-generator-config.ymal
# Config options for the dart-dio generator
pubName: app_api
pubVersion: 0.0.1
pubDescription: "App API"
dateLibrary: core
serializationLibrary: json_serializable
equalityCheckMethod: equatable
Steps to reproduce
run
openapi-generator generate -i openapi_docs.yaml -g dart-dio -c open-generator-config.yaml --enable-post-process-file
mpoimerjoelbrostrom
Activity
mpoimer commentedon Jun 2, 2025
Having the same issue.
Any updates on this?
joelbrostrom commentedon Jun 3, 2025
I'm afraid not.
I had to circumvent the generated endpoint and call my endpoint directly from my repository instead.
matthewnitschke-wk commentedon Jun 4, 2025
@mpoimer @joelbrostrom Ran into a similar issue, but specifically with the non-streamed binary result
A fix for this can be found here: #21379
Could either of you test my generator changes to see if it covers the issue you're running into as well?