Skip to content

Feedback form reports success without confirming delivery (related to sentry-dart#4016) #6766

Description

@lucas-zimerman

Description

sentry-dart issue getsentry/sentry-dart#4016 reports that the Flutter feedback form always treats a returned id as success, even when the feedback was never actually sent, discarding the user's draft in the process. While investigating that report I compared it against FeedbackForm here and against the browser widget in sentry-javascript, and this repo has a related (though mechanically different) problem.

What I found in FeedbackForm.tsx

handleFeedbackSubmit calls captureFeedback (from @sentry/core) without awaiting anything, then immediately calls onSubmitSuccess, shows the success alert, and marks _didSubmitForm = true:

captureFeedback(userFeedback, attachments ? { attachments } : undefined);
onSubmitSuccess({ ... });
feedbackAlertDialog(text.successMessageText, '');
onFormSubmitted();
this._didSubmitForm = true;

captureFeedback in @sentry/core is synchronous and fire-and-forget — it just calls scope.captureEvent(...) and returns the generated event id immediately; it does not wait for the transport to actually deliver the envelope. So a network error, a non-2xx response, or beforeSendFeedback dropping the event happens entirely after this function has already reported success to the caller. The catch block only ever fires for a synchronous throw before the event is queued (e.g. a bad argument), not for delivery failure.

The practical effect: users can get "Thank you for your feedback" even though the feedback never reached Sentry, and because _didSubmitForm is true, componentWillUnmount clears the saved draft instead of preserving it — so there's nothing left to retry or recover.

There's also no in-flight guard on the submit button: if a consumer supplies onFormSubmitted (so the form isn't auto-hidden via isVisible: false at L143), repeated taps just fire captureFeedback again with no loading/disabled state.

Contrast with the browser widget

sentry-javascript's own feedback widget (packages/feedback/src/modal/components/Form.tsx + core/sendFeedback.ts) doesn't have this problem: sendFeedback() returns a promise that only resolves after afterSendEvent reports a 2xx, and explicitly rejects on non-2xx/403/a 30s timeout. handleSubmit awaits that, disables the whole <fieldset> while isSubmitting, and only calls onSubmitSuccess after confirmed delivery — on failure it keeps the form open with the data intact and calls onSubmitError.

Suggested fix

Have FeedbackForm await confirmation of actual delivery (mirroring what sendFeedback() does in the browser widget — hooking client.on('afterSendEvent', ...) for the generated event id, or similar) before calling onSubmitSuccess / clearing the draft, and disable the submit control while that's pending.

I'm not proposing a specific implementation here — flagging this now since it came up directly while investigating the Dart issue, and wanted to get it on your radar before scoping a fix.

Activity

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

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions