[cloud_firestore]: Apple pipeline parser passes an NSString where FIRExprBridge is expected for findNearest `distance_field` (incompatible pointer types warning; unrecognized selector crash if reached)
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 20/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Estancado
- Stack tecnológico
- ios, macos, objective-c
- Área
- backend
Línea de trabajo
Read the find_nearest branch in the iOS and macOS FLTPipelineParser.m files and compare its distance_field handling with the nearby unnest branch. The open related PR #18607 already replaces this parser and wraps the field name correctly; check that PR's status before choosing work here. Done means the Apple parser passes an expression bridge for distance_field without the incompatible pointer warning.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Is there an existing issue for this?
- I have searched the existing issues.
Which plugins are affected?
Other (cloud_firestore)
Which platforms are affected?
iOS, macOS
Description
In the Apple pipeline parser, the find_nearest stage reads distance_field as an NSString and passes it straight to the SDK's distanceField: parameter. That parameter is typed as an expression bridge (FIRExprBridge * / __FIRExprBridge * on SDK 13).
Build time: every iOS/macOS build prints this warning:
cloud_firestore-6.10.0/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m:1570:66: warning: incompatible pointer types sending 'NSString *' to parameter of type 'FIRExprBridge * _Nullable' [-Wincompatible-pointer-types]
1570 | distanceField:distanceField];
| ^~~~~~~~~~~~~
Run time: the SDK stores the value and later sends it cppExprWithReader:, a method that NSString does not have. So any find_nearest stage that carries distance_field throws an uncaught NSInvalidArgumentException (unrecognized selector), and the app terminates.
Where
The plugin code is the same in every release since pipelines shipped, including the latest one:
| Version | iOS file:line |
|---|---|
| 6.3.0 – 6.4.1 | FLTPipelineParser.m:1105 (read), :1137 (pass) |
| 6.5.0 | :1188 (read), :1220 (pass) |
| 6.9.0 – 6.10.0 | :1538 (read), :1570 (pass) |
| 7.0.0 (latest on pub.dev) | FLTPipelineParser.m:1578 (read), :1610 (pass) |
main @ 9b821bc18500b9ae55a9cb74b0be949cb64bcd19 |
same as 7.0.0 |
- The macOS copy (
macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m) is byte-identical to the iOS file onmain, so it has the same bug. - The code was introduced in d734cf0885 (#18183, "feat: support for Firestore Pipelines").
- The file was last changed in aca14eab53 (#18783, SDK 13 rename), which did not touch this branch.
Permalinks (main @ 9b821bc):
- iOS: https://github.com/firebase/flutterfire/blob/9b821bc18500b9ae55a9cb74b0be949cb64bcd19/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m#L1578-L1610
- macOS: https://github.com/firebase/flutterfire/blob/9b821bc18500b9ae55a9cb74b0be949cb64bcd19/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m#L1578-L1610
The plugin code (7.0.0 / main):
NSString *distanceField = [args[@"distance_field"] isKindOfClass:[NSString class]]
? args[@"distance_field"]
: nil;
...
stage = [[__FIRFindNearestStageBridge alloc] initWithField:embeddingField
vectorValue:queryVector
distanceMeasure:distanceMeasure
limit:limit
distanceField:distanceField]; // NSString *
Why it crashes
-
The SDK declares the parameter as an expression. firebase-ios-sdk 13.0.0,
Firestore/Source/Public/FirebaseFirestore/FIRPipelineBridge.hL179-L185 (12.19.0 has the same declaration, withFIRnames instead of__FIR):@interface __FIRFindNearestStageBridge : __FIRStageBridge - (id)initWithField:(__FIRFieldBridge *)field vectorValue:(FIRVectorValue *)vectorValue distanceMeasure:(NSString *)distanceMeasure limit:(NSNumber *_Nullable)limit distanceField:(__FIRExprBridge *_Nullable)distanceField; -
The SDK treats the stored value as an expression.
Firestore/Source/API/FIRPipelineBridge.mmL839-L842 (13.0.0; the same lines in 12.19.0):if (_distanceField) { std::shared_ptr<Expr> cpp_distance_field = [_distanceField cppExprWithReader:reader]; optional_value.emplace( std::make_pair(std::string("distance_field"), cpp_distance_field->to_proto())); } -
Nothing catches the exception. This runs synchronously from
executeWithCompletion:→cppPipelineWithReader:→cppStageWithReader:. Neither the plugin'sexecutePipelineWithFirestore:...nor the Pigeon handler wraps the call in@try. -
The SDK's own Swift API wraps the name. It never passes a plain string (
Firestore/Swift/Source/Stages.swiftL314 @ 13.0.0):distanceField: distanceField.map { Field($0).toBridge() } ?? nil -
The same parser already does this correctly elsewhere. The
unnestbranch a few lines above wraps its optionalindex_fieldcorrectly (FLTPipelineParser.mL1567-L1569 @ main):__FIRExprBridge *indexFieldExpr = (indexFieldStr.length > 0) ? [[__FIRFieldBridge alloc] initWithName:indexFieldStr] : nil;
A minimal Objective-C program confirms the runtime failure mode. When an NSString stands in for the expression object and receives cppExprWithReader:, it raises:
NSInvalidArgumentException: -[NSTaggedPointerString cppExprWithReader:]: unrecognized selector sent to instance 0x...
Reproducing the issue
Build-time warning: add cloud_firestore (6.3.0 – 7.0.0) to a Flutter app and build for iOS or macOS. The warning above appears for FLTPipelineParser.m.
Runtime: the public Pipeline.findNearest(...) in cloud_firestore has no distanceField parameter today (lib/src/pipeline.dart L418, lib/src/pipeline_stage.dart L177-L208). So the native branch is reached through the public platform interface, which sends the stage map to the native parser unchanged. Add cloud_firestore_platform_interface to pubspec.yaml and run on iOS:
import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart';
import 'package:firebase_core/firebase_core.dart';
Future<void> reproduce() async {
final firestore = FirebaseFirestorePlatform.instanceFor(
app: Firebase.app(),
databaseId: '(default)',
);
await firestore
.pipeline([
{'stage': 'collection', 'args': {'path': 'items'}},
])
.addStage({
'stage': 'find_nearest',
'args': {
'vector_field': 'embedding',
'vector_value': [0.1, 0.2, 0.3],
'distance_measure': 'cosine',
'distance_field': 'distance',
},
})
.execute();
}
- Expected: the stage runs, and each result carries the computed distance in
distance, as it does on web. - Actual (from the code path above): an uncaught
NSInvalidArgumentException(-[... cppExprWithReader:]: unrecognized selector) terminates the app.
I traced this by reading the code. The runtime crash has not been run end to end on a device.
Proposed fix
Wrap the field name in the SDK's field expression bridge before passing it, as the unnest branch and the SDK's Swift FindNearest stage already do. The patch below targets main @ 9b821bc, with SDK 13 names. It applies cleanly to both the iOS and macOS copies (checked with git apply --check). Type-checked against the 13.0.0 header with clang -fsyntax-only -Wincompatible-pointer-types, the current call reproduces the warning and the patched call compiles without it.
--- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m
+++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m
@@ -1603,11 +1603,14 @@
return nil;
}
FIRVectorValue *queryVector = [[FIRVectorValue alloc] initWithArray:numbers];
+ __FIRExprBridge *distanceFieldExpr =
+ (distanceField.length > 0) ? [[__FIRFieldBridge alloc] initWithName:distanceField]
+ : nil;
stage = [[__FIRFindNearestStageBridge alloc] initWithField:embeddingField
vectorValue:queryVector
distanceMeasure:distanceMeasure
limit:limit
- distanceField:distanceField];
+ distanceField:distanceFieldExpr];
} else {
if (error)
*error = parseError([NSString stringWithFormat:@"Unknown pipeline stage: %@", stageName]);
--- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m
+++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m
@@ -1603,11 +1603,14 @@
return nil;
}
FIRVectorValue *queryVector = [[FIRVectorValue alloc] initWithArray:numbers];
+ __FIRExprBridge *distanceFieldExpr =
+ (distanceField.length > 0) ? [[__FIRFieldBridge alloc] initWithName:distanceField]
+ : nil;
stage = [[__FIRFindNearestStageBridge alloc] initWithField:embeddingField
vectorValue:queryVector
distanceMeasure:distanceMeasure
limit:limit
- distanceField:distanceField];
+ distanceField:distanceFieldExpr];
} else {
if (error)
*error = parseError([NSString stringWithFormat:@"Unknown pipeline stage: %@", stageName]);
For a 6.x patch release, the change is the same with the SDK 12 names: FIRExprBridge / FIRFieldBridge / FIRFindNearestStageBridge, at 6.10.0 FLTPipelineParser.m L1565-L1570.
Firebase Core version
firebase_core 4.15.0 (Firebase Apple SDK 12.19.0) with cloud_firestore 6.10.0. The code is unchanged in cloud_firestore 7.0.0 with firebase_core 5.0.0 (Firebase Apple SDK 13.0.0 via Swift Package Manager).
Flutter Version
3.47.5 (stable), Xcode 27.1 (27A9275)
Relevant Log Output
FLTPipelineParser.m:1570:66: warning: incompatible pointer types sending 'NSString *' to parameter of type 'FIRExprBridge * _Nullable' [-Wincompatible-pointer-types]
Flutter dependencies
cloud_firestore: 6.10.0, firebase_core: 4.15.0. Also checked against cloud_firestore: 7.0.0 / firebase_core: 5.0.0 and main.
Additional context and comments
Impact
- Build: every iOS/macOS build of cloud_firestore 6.3.0 – 7.0.0 shows this warning. Projects that build with warnings as errors fail.
- Run time today: low. The crash needs
distance_fieldto reach the Apple parser, and the publiccloud_firestoreDart API does not send it yet. Only callers that go through the platform interface can hit it. - Run time after a Dart change: when
Pipeline.findNearestgains adistanceFieldoption, every Apple app that uses it will crash. Web already supports this option.
Platform parity (related)
The distance_field argument is handled differently on each platform:
| Platform | Handling of distance_field |
|---|---|
| Web | supported: cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart L755-L767 |
| Apple | read, but with the wrong type (this issue) |
| Android | ignored: PipelineStageHandlers.java L308-L338 |
| Dart | Pipeline.findNearest does not expose it |
Related PR
#18607 (open; migrates the Apple plugin to Swift) replaces this file. Its PipelineParser.swift wraps the name correctly (distanceField.map { FieldBridge(name: $0) }), so merging it would also fix this. It currently has merge conflicts and predates the SDK 13 __ renames from #18783. Until it lands, the three-line fix above removes both the warning and the crash path.
- Lenguaje dominante
- Dart
- Estrellas
- 9.3k
- Forks
- 4.1k
- Merge medio
- 1 d 12 h
- PR fusionados (30 d)
- 79
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de firebase/flutterfire
-
[firebase_messaging]: Android ANR during background service destruction — main thread blocked in releaseWakeLockPosiblemente ocupada @SelaseKay la tomó hace 2 días. AbiertoNeeds Attention platform: android plugin: messaging type: bug
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
firebase/flutterfire#18866 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
blocked: customer-response Needs Attention platform: ios plugin: messaging Stale type: bug
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
firebase/flutterfire#18776 · 5 comentarios ·
Los mantenedores suelen responder en 1 día
-
[firebase_storage] Windows native crash in upload progress callback, sink ownership and thread dispatchQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abiertoblocked: flutter platform: windows plugin: storage reproduced type: bug
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
firebase/flutterfire#18664 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
[core] Decouple platform_interface from Flutter for pure-Dart webQuizá libre de nuevo @Lyokone la tomó hace 38 días y no hay ningún pull request abierto. AbiertoNeeds Attention platform: all platform: web plugin: core type: enhancement
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
firebase/flutterfire#18645 · 3 comentarios · 2 reacciones · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
blocked: firebase-sdk platform: android plugin: messaging reproduced type: bug
Dificultad 3/5 1-2 días Aptitud para principiantes 56/100
firebase/flutterfire#18644 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de firebase/flutterfire
Issues similares
-
type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 80/100
decentespresso/decaid#1028 ·
Los mantenedores suelen responder en 1 día
-
Update checksums / Verify firmware give no success or error feedback (looks like a dead button)Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
canonical/firmware-updater#443 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
Los mantenedores suelen responder en 3 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
Los mantenedores suelen responder en 1 día