[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)
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 20/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Ferma
- Stack tecnologico
- ios, macos, objective-c
- Ambito
- backend
Direzione di ricerca
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.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- Dart
- Stelle
- 9.3k
- Fork
- 4.1k
- Merge medio
- 1g 22h
- PR unite (30g)
- 79
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di firebase/flutterfire
-
blocked: customer-response Needs Attention platform: ios plugin: messaging Stale type: bug
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
firebase/flutterfire#18776 · 5 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
[firebase_storage] Windows native crash in upload progress callback, sink ownership and thread dispatchForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertablocked: flutter platform: windows plugin: storage reproduced type: bug
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
firebase/flutterfire#18664 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
[core] Decouple platform_interface from Flutter for pure-Dart webForse di nuovo libera @Lyokone l’ha presa 36 giorni fa e non c’è nessuna pull request aperta. ApertaNeeds Attention platform: all platform: web plugin: core type: enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
firebase/flutterfire#18645 · 3 commenti · 2 reazioni · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
blocked: firebase-sdk platform: android plugin: messaging reproduced type: bug
Difficoltà 3/5 1-2 giorni Idoneità per principianti 56/100
firebase/flutterfire#18644 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
[firebase_database, windows] Listener callbacks are delivered on a non-platform thread and crash the processForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertablocked: flutter platform: windows plugin: database reproduced type: bug
Difficoltà 4/5 3-5 giorni Idoneità per principianti 52/100
firebase/flutterfire#18630 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di firebase/flutterfire
Issue simili
-
bug enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
AOSSIE-Org/Ell-ena#356 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
espresso3389/pdfrx#776 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
MostroP2P/app#881 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
[기능 제안]Apertaenhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
atsign-foundation/at_server#2896 ·
I maintainer di solito rispondono entro 1 giorno