Skip to content

SensorConfig.multiple crashes with "Multiple widgets used the same GlobalKey" — module-level previewWidgetKey collides between primary and PiP previews #646

Description

@billyward3

Environment

  • camerawesome: 2.5.0 (latest on pub.dev as of 2026-05-31)
  • Flutter: 3.x (stable)
  • Device: iPhone 16 Plus, iOS 18.x
  • CamerawesomePlugin.isMultiCamSupported() returns true

Symptom

Using SensorConfig.multiple(...) on either CameraAwesomeBuilder.awesome or CameraAwesomeBuilder.custom floods the log with:

FlutterError: Multiple widgets used the same GlobalKey.
The key [GlobalKey#xxxxx] was used by multiple widgets. The parents of those widgets were:
- Padding(padding: EdgeInsets.zero, dependencies: [Directionality], ...)
- Padding(padding: EdgeInsets.zero, dependencies: [Directionality], ...)
A GlobalKey can only be specified on one widget at a time in the widget tree.

Visible effect: both the primary preview and the PiP preview render black (or one of them does). On capture, the primary sensor file is never written; only the secondary (PiP) sensor produces a file. The capture event's multiple.fileBySensor is missing the primary entry.

Root cause

lib/src/widgets/preview/awesome_preview_fit.dart:7:

final previewWidgetKey = GlobalKey();

This is a module-level singleton GlobalKey. It is then assigned to the wrapping InteractiveViewer on line 159 of the same file:

InteractiveViewer(
  key: previewWidgetKey,
  transformationController: transformController,
  scaleEnabled: false,
  constrained: false,
  panEnabled: false,
  ...
)

When SensorConfig.multiple is in effect, the package mounts PreviewFitWidget twice (once for the primary preview, once for the PiP overlay). Both instances attach the same module-level GlobalKey, which Flutter rejects: a GlobalKey must be unique in the widget tree at any given time.

The resulting tree-finalize assertion appears to be what prevents the second AVCaptureMultiCamSession output from binding correctly on iOS — only the secondary sensor produces a capture file.

Reproduction

The package's own example/lib/multi_camera.dart should reproduce this on any iOS 13+ device with multi-cam support (iPhone XS or later).

sensorConfig: SensorConfig.multiple(
  sensors: [
    Sensor.type(SensorType.telephoto),  // matches the example's iOS branch
    Sensor.position(SensorPosition.front),
  ],
  flashMode: FlashMode.none,
  aspectRatio: CameraAspectRatios.ratio_4_3,
),

Suggested fix

The InteractiveViewer's scaleEnabled and panEnabled are both false in this code path. The GlobalKey does not appear to be load-bearing for the InteractiveViewer's state — it can either be removed, or scoped per-instance by making it a final _previewWidgetKey = GlobalKey() inside _AnimatedPreviewFitState (or similar per-mount scope).

If the key is needed elsewhere (e.g., for transformationController coordination with another widget I haven't traced), the simplest correctness fix is to make it per-instance.

Happy to send a PR if a maintainer can confirm which scope is intended.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions