Summary
ChannelRepository.importChannel() (used by the "Add channel via link/QR code" dialog) silently returns null when the per-companion private-channel index pool is exhausted, instead of surfacing a specific error. The UI then shows the generic "Invalid channel link / key" snackbar, which is misleading -- the link/key is valid, there's just no free channel slot.
This is not platform-specific. It reproduces on any platform once a companion already has _maxPrivateChannels (currently 7) private channels registered.
Where
lib/repositories/channel_repository.dart, importChannel():
- Computes
nextIndex via _nextIndexFor(localOnly, companionKey) (line ~313).
- If no index is available,
_nextIndexFor returns null, and importChannel just does if (nextIndex == null) return null; -- no exception, no distinguishing error.
- Contrast with
createChannel() / createPrivateChannel() in the same file, which handle the identical "no free index" case by throwing a specific StateError('Maximum number of channels ($_maxPrivateChannels) reached').
importChannel()'s blanket try { ... } catch (_) { return null; } also swallows firmware-registration failures (_registerChannelWithFirmware returning !isSuccess) the same way, whereas the create-channel paths surface result.errorCode (including a specific message for error code 3 / max channels).
Repro
- Have a companion with 7 private (non-public) channels already registered (indices 1-7 all used).
- Try to import an 8th channel via a
meshcore://channel/add?name=...&secret=... link, either by pasting the full URL or scanning a QR code, in the "Add channel via link/QR code" dialog.
- Observe: "Invalid channel link / key" snackbar, even though the link/secret are well-formed and decode correctly.
Expected
importChannel() should distinguish failure modes the same way createChannel/createPrivateChannel already do, and the UI should show a specific message like "Maximum number of channels reached" instead of the generic invalid-link message.
Suggested fix
Either:
- Have
importChannel() throw the same StateErrors that createChannel/createPrivateChannel throw for max-channels-reached and firmware-registration failure, and let the dialog's existing catch (e) block (around lib/screens/channels_screen.dart) display e.toString(), or
- Change
importChannel()'s return type to something that can carry a specific failure reason instead of ChannelData?.
Summary
ChannelRepository.importChannel()(used by the "Add channel via link/QR code" dialog) silently returnsnullwhen the per-companion private-channel index pool is exhausted, instead of surfacing a specific error. The UI then shows the generic "Invalid channel link / key" snackbar, which is misleading -- the link/key is valid, there's just no free channel slot.This is not platform-specific. It reproduces on any platform once a companion already has
_maxPrivateChannels(currently 7) private channels registered.Where
lib/repositories/channel_repository.dart,importChannel():nextIndexvia_nextIndexFor(localOnly, companionKey)(line ~313)._nextIndexForreturnsnull, andimportChanneljust doesif (nextIndex == null) return null;-- no exception, no distinguishing error.createChannel()/createPrivateChannel()in the same file, which handle the identical "no free index" case by throwing a specificStateError('Maximum number of channels ($_maxPrivateChannels) reached').importChannel()'s blankettry { ... } catch (_) { return null; }also swallows firmware-registration failures (_registerChannelWithFirmwarereturning!isSuccess) the same way, whereas the create-channel paths surfaceresult.errorCode(including a specific message for error code 3 / max channels).Repro
meshcore://channel/add?name=...&secret=...link, either by pasting the full URL or scanning a QR code, in the "Add channel via link/QR code" dialog.Expected
importChannel()should distinguish failure modes the same waycreateChannel/createPrivateChannelalready do, and the UI should show a specific message like "Maximum number of channels reached" instead of the generic invalid-link message.Suggested fix
Either:
importChannel()throw the sameStateErrors thatcreateChannel/createPrivateChannelthrow for max-channels-reached and firmware-registration failure, and let the dialog's existingcatch (e)block (aroundlib/screens/channels_screen.dart) displaye.toString(), orimportChannel()'s return type to something that can carry a specific failure reason instead ofChannelData?.