Skip to content

fix: prevent unhandled rejections and stale audio URL leaks in useTTS.js - #1166

Merged
itzzavdhesh merged 2 commits into
itzzavdhesh:mainfrom
hrshjswniii:BugFix/TTS-Audio-URL-Leaks
Aug 10, 2026
Merged

fix: prevent unhandled rejections and stale audio URL leaks in useTTS.js#1166
itzzavdhesh merged 2 commits into
itzzavdhesh:mainfrom
hrshjswniii:BugFix/TTS-Audio-URL-Leaks

Conversation

@hrshjswniii

@hrshjswniii hrshjswniii commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

🚀 Program

GSSoC

📝 Description

This PR resolves unhandled AbortError promise rejections and stale Blob audio URL memory leaks in useTTS.js during rapid speech synthesis requests.

Key fixes:

  1. Blob Audio URL Garbage Collection: Added updateAudioUrl helper and an unmount cleanup useEffect handler to revoke stale blob: URLs via URL.revokeObjectURL(prevUrl).
  2. Clean Abort Handling: Inspected controller.signal.aborted and AbortError in both outer synthesis and fallback catch blocks. Aborted requests now resolve cleanly without throwing unhandled promise rejections to caller components (Call.jsx, TextToSpeech.jsx).
  3. Unit Tests (useTTS.test.js): Added Vitest test assertions for useTTS.

🔗 Related Issue

Closes #1133

🔄 Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🔍 SEO improvement
  • 🎨 Style / UI improvement
  • ♿ Accessibility improvement
  • 📝 Documentation
  • ⚙️ CI / configuration
  • 🧹 Refactor / cleanup

🧪 How to Test

  1. Open http://localhost:5173 in a browser.
  2. Go to the Call page, enter text, and rapidly click Speak multiple times in quick succession.
  3. Check browser DevTools console to verify zero AbortError unhandled rejections occur.
  4. Run client tests: npm run test --workspace client and verify all tests pass.

✅ Checklist

  • I am contributing under GSSoC, NSOC, SSOC, or ELUSOC
  • My code follows the project's existing style
  • I have tested my changes in a browser
  • I have linked the related issue above
  • My PR title follows Conventional Commits format (e.g. fix: prevent unhandled rejections and stale audio URL leaks in useTTS.js)

Summary by cubic

Fixes unhandled AbortError rejections and stops stale blob: audio URL leaks in useTTS. Rapid speak calls no longer log errors, and audio URLs are cleaned up on update and unmount.

  • Bug Fixes
    • Use server audioUrl directly and route updates through updateAudioUrl; revoke previous blob: URLs, abort in-flight requests, and clean up on unmount.
    • Handle aborts safely: early-return on controller.signal.aborted, catch AbortError in both primary and fallback paths, and keep engine/status updates consistent.

Written for commit 945f3e2. Summary will update on new commits.

Review in cubic

@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

@hrshjswniii is attempting to deploy a commit to the itzzavdhesh's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown

✍️ DCO Sign-off Needed

Hey @hrshjswniii! 👋 One or more commits in this PR are missing a Signed-off-by: line.

Warning

  • abb79a6 fix: prevent unhandled rejections and stale audio URL leaks in useTTS.js
  • 945f3e2 Merge branch 'main' into BugFix/TTS-Audio-URL-Leaks

How to fix:

For the latest commit:

git commit --amend --signoff
git push --force-with-lease

For multiple commits, replace N with the number to update:

git rebase --signoff HEAD~N
git push --force-with-lease

This comment will update automatically after you push.


🤖 VoiceForge Automation · Updates automatically on edits

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@hrshjswniii, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ca11b71b-85fe-47b1-941c-3591cec39a0a

📥 Commits

Reviewing files that changed from the base of the PR and between 65b0f09 and 945f3e2.

📒 Files selected for processing (2)
  • client/src/hooks/useTTS.js
  • client/src/hooks/useTTS.test.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown

🎉 PR Ready for Mentor Review

Hey @hrshjswniii! 👋 Your PR passed all checks and is now in the GSSoC review queue.

Note

🔗 Closing: #1133 · 📐 60 lines across 2 file(s) · 📬 Already requested or no eligible reviewer found

@sabeenaviklar @Anushreebasics @itsdakshjain @snehkris @Mrigakshi-Rathore @Itzzavdheshh @Nitya-003 @4f4d @lovestaco, this PR is ready for your review — please confirm scope, check behavior and tests, then approve or request changes.

Important

This is not an approval. Please wait for mentor feedback before expecting a merge. If changes are requested, push them to this same branch and keep the PR focused on the linked issue.


🤖 VoiceForge Automation · Updates automatically on edits

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="client/src/hooks/useTTS.js">

<violation number="1" location="client/src/hooks/useTTS.js:124">
P2: Rapid replacement requests can still leave an earlier browser-fallback utterance audible. `controller.abort()` does not cancel `speechSynthesis`; wire the signal to `speechSynthesis.cancel()` (including unmount) so this cancelled path stops playback immediately.</violation>
</file>

<file name="client/src/hooks/useTTS.test.js">

<violation number="1" location="client/src/hooks/useTTS.test.js:1">
P2: The test coverage for this PR's core fixes (abort handling and blob URL cleanup) is minimal. The single test only verifies that the default export is a function, which is a module-level assertion that doesn't exercise the runtime behavior of the hook. The PR description lists "Unit Tests" as a key deliverable, and the existing test in the codebase (`MessageCard.test.js`) sets a precedent of testing edge cases, mock timers, and behavioral assertions. The `vitest` environment is `"node"` and `@testing-library/react` is not in the dependencies, but the test could still be extended to verify the hook's return shape, state transitions, or—after installing `jsdom` and `@testing-library/react`—runtime coverage of abort handling and URL revocation.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

const payload = await response.json();
const nextAudioUrl = payload.audioUrl;

if (controller.signal.aborted) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Rapid replacement requests can still leave an earlier browser-fallback utterance audible. controller.abort() does not cancel speechSynthesis; wire the signal to speechSynthesis.cancel() (including unmount) so this cancelled path stops playback immediately.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/src/hooks/useTTS.js, line 124:

<comment>Rapid replacement requests can still leave an earlier browser-fallback utterance audible. `controller.abort()` does not cancel `speechSynthesis`; wire the signal to `speechSynthesis.cancel()` (including unmount) so this cancelled path stops playback immediately.</comment>

<file context>
@@ -90,8 +121,12 @@ export default function useTTS() {
       const payload = await response.json();
       const nextAudioUrl = payload.audioUrl;
 
+      if (controller.signal.aborted) {
+        return;
+      }
</file context>

@@ -0,0 +1,8 @@
import { describe, it, expect } from "vitest";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The test coverage for this PR's core fixes (abort handling and blob URL cleanup) is minimal. The single test only verifies that the default export is a function, which is a module-level assertion that doesn't exercise the runtime behavior of the hook. The PR description lists "Unit Tests" as a key deliverable, and the existing test in the codebase (MessageCard.test.js) sets a precedent of testing edge cases, mock timers, and behavioral assertions. The vitest environment is "node" and @testing-library/react is not in the dependencies, but the test could still be extended to verify the hook's return shape, state transitions, or—after installing jsdom and @testing-library/react—runtime coverage of abort handling and URL revocation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At client/src/hooks/useTTS.test.js, line 1:

<comment>The test coverage for this PR's core fixes (abort handling and blob URL cleanup) is minimal. The single test only verifies that the default export is a function, which is a module-level assertion that doesn't exercise the runtime behavior of the hook. The PR description lists "Unit Tests" as a key deliverable, and the existing test in the codebase (`MessageCard.test.js`) sets a precedent of testing edge cases, mock timers, and behavioral assertions. The `vitest` environment is `"node"` and `@testing-library/react` is not in the dependencies, but the test could still be extended to verify the hook's return shape, state transitions, or—after installing `jsdom` and `@testing-library/react`—runtime coverage of abort handling and URL revocation.</comment>

<file context>
@@ -0,0 +1,8 @@
+import { describe, it, expect } from "vitest";
+import useTTS from "./useTTS";
+
</file context>

@Nitya-003 Nitya-003 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hrshjswniii Resolve the conflicts and comments.

Image

@itsdakshjain itsdakshjain left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good
Resolve the branch merge conflicts

@itsdakshjain itsdakshjain added the mentor:itsdakshjain GSSoC: Mentor-@itsdakshjain label Jul 29, 2026
@github-actions github-actions Bot added mentor:Nitya-003 Applied by mentor automation needs revision and removed ready for review labels Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

🔄 Changes Requested

Hey @hrshjswniii! 👋 A mentor has reviewed your PR and requested some changes.

Warning

Please review the feedback above, update this same branch, and keep the PR focused on the linked issue.

Once you push your updates, the review flow will continue automatically on this same PR.


🤖 VoiceForge Automation · Updates automatically on edits

@itzzavdhesh
itzzavdhesh merged commit cb2a674 into itzzavdhesh:main Aug 10, 2026
7 of 9 checks passed
@github-actions

Copy link
Copy Markdown

🎊 PR Merged Successfully

Hey @hrshjswniii! 👋 Congratulations and thank you for your contribution to VoiceForge!

Note

🔗 Linked issue(s): #1133 · ✅ Marked as merged and complete

Maintainers may still handle final cleanup, release notes, or follow-up tracking after the merge.


🤖 VoiceForge Automation · Updates automatically on edits

@itzzavdhesh itzzavdhesh added SSoC26 SSOC Hard hard ELUSOC ELUSOC VETERAN VETERAN type:feature type:feature type:refactor type:refactor mentor:Anushreebasics GSSoC: Mentor-@Anushreebasics mentor:sabeenaviklar GSSoC: Mentor-@sabeenaviklar labels Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] : Unhandled Rejections and Stale Audio URL Leaks in useTTS.js

4 participants