Skip to content

Report voice recording failures via onRecordingErrorCallback - #205

Open
dorklein wants to merge 1 commit into
flutter:mainfrom
GD-Smart-Bill:voice-recording-error-callback
Open

dorklein wants to merge 1 commit into
flutter:mainfrom
GD-Smart-Bill:voice-recording-error-callback

Conversation

@dorklein

@dorklein dorklein commented Nov 5, 2026

Copy link
Copy Markdown

When the microphone can't be used (permission denied, no device, the recorder fails to start), tapping the record button does nothing visible. ChatInput awaits WaveformRecorderController.startRecording() and stopRecording() with no error handling, so the error escapes as an uncaught async error and the app gets no chance to tell the user.

Change

  • ChatInput catches errors from startRecording() and stopRecording() and hands them to LlmChatView.
  • New optional LlmChatView.onRecordingErrorCallback(BuildContext context, Object error), next to onErrorCallback and onCancelCallback and following the same pattern. If it isn't set, the chat shows a snackbar with strings.unableToRecordAudio, which is what the stop path already shows when no file was recorded.

Apps that want their own message, or want to log the error, pass the callback. Everyone else now gets the existing localized "Unable to record audio" message.

Test

test/voice_recording_error_test.dart mocks the record method channel so the microphone permission is refused, taps Record Audio, and checks that:

  • the default snackbar is shown, and
  • onRecordingErrorCallback receives the error and replaces the snackbar.

Depends on csells/waveform_recorder#13 and #14. With waveform_recorder 1.8.1 (the current release), a failed start leaves the controller in the recording state. The next rebuild of the chat input then throws Exception: Not recording from amplitudeStream, so this test fails on 1.8.1 for that reason, not because of this change. #13 leaves the controller idle after a failed start, and #14 makes a refused permission fail the start. With both (I ran it with a dependency_overrides on a branch that has them), the new tests and the existing ones pass, and dart analyze --fatal-infos and dart format are clean. Once they're released, the waveform_recorder constraint here can move to that version; I'm happy to add that bump to this PR.

🤖 Generated with Claude Code

@google-cla

google-cla Bot commented Nov 5, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

ChatInput awaited the recorder's startRecording() and stopRecording() with
no error handling, so a denied or missing microphone surfaced as an
uncaught async error and the user saw nothing. Catch those errors and pass
them to a new LlmChatView.onRecordingErrorCallback. By default, show the
existing unableToRecordAudio snackbar, as the stop path already does when
no file was recorded.
@dorklein
dorklein force-pushed the voice-recording-error-callback branch from 6275a1c to 9bf29cb Compare November 5, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant