Error Handling
Relevant source files
The following files were used as context for generating this wiki page:Introduction
Error handling in the youtube_notes application is designed to be robust and user-centric, preventing application crashes and providing clear feedback. The strategy combines backend API error responses, graceful degradation in frontend services, and stateful error management within React hooks to inform the UI. This ensures that failures in one part of the system, such as a failed AI generation or transcript fetch, do not disrupt the overall user experience. Key mechanisms include specific HTTP status codes from the backend, "fail-soft" approaches in AI services that return fallback data, and user-facing alerts with actionable options like retrying an operation or configuring an API key.
Backend API Error Handling
The backend, a FastAPI application, is the first line of defense, handling errors related to transcript fetching. It uses specific HTTP exceptions to communicate the nature of the failure to the frontend.
Sources: api/index.py, tests/api_test.py
Transcript Fetching (/api/transcript)
The /api/transcript endpoint has a comprehensive try...except block to handle various failure scenarios when interacting with the youtube_transcript_api library.
The following diagram illustrates the error handling flow for a transcript request.
Sources: api/index.py:65-87, tests/api_test.py
Specific API Errors
The API catches specific exceptions from the youtube_transcript_api library and maps them to a 404 Not Found status, as the transcript is considered a resource that is unavailable.
| Exception | HTTP Status | Detail Message |
|---|---|---|
TranscriptsDisabled | 404 | Transcript unavailable. |
NoTranscriptFound | 404 | Transcript unavailable. |
VideoUnavailable | 404 | Transcript unavailable. |
Sources: api/index.py:75-78, tests/api_test.py:46-70
Generic and Critical Errors
For unexpected exceptions, the server returns a generic 500 Internal Server Error. It also includes a specific check for error messages containing "Too Many Requests" or "Sign in", which indicate that the server's IP is being blocked by YouTube. In this case, it returns a 403 Forbidden to signal a service-level block.
# api/index.py:79-87
except Exception as e:
# ...
error_msg = str(e)
if "Too Many Requests" in error_msg or "Sign in" in error_msg:
print("Action Required: YouTube Blocking IP")
raise HTTPException(status_code=403, detail="Service temporarily blocked by YouTube.")
# Generic client error
raise HTTPException(status_code=500, detail="Internal Server Error")
Sources: api/index.py:79-87
Frontend Service-Level Handling
Frontend services that wrap API calls implement their own error handling logic, deciding whether to propagate errors or handle them gracefully.
Gemini Service (geminiService.ts)
The geminiService is designed with a "fail-soft" or graceful degradation approach. Instead of throwing an error and crashing the application flow, it catches exceptions, logs them, and returns a sensible fallback value.
This sequence diagram shows how a call to cleanTranscriptText handles an API failure.
Sources: services/geminiService.ts:47-56
cleanTranscriptText: If the Gemini API call fails, it logs the error and returns the originalrawText. This ensures that even if AI cleaning fails, the user's note is still created with the un-cleaned text.generateAIContent: This generic function, used by content generators likegenerateLinkedInPost, catches any error during the API call or JSON parsing and returns the providedfallbackValue.generateTwitterThread: If the API call fails, this function throws the error, which is then handled by the calling hook (useContentGenerator).
Sources: services/geminiService.ts:47-56, services/geminiService.ts:108-124, services/geminiService.ts:98-101
API Key Validation
The service provides a validateApiKey function that returns a boolean. It makes a test call to the Gemini API and returns true on success and false on any exception, providing a simple way for the UI to check key validity without crashing.
Sources: services/geminiService.ts:58-69
Frontend UI and State Handling
React hooks are responsible for managing asynchronous operations, catching errors from services, and updating the component state to display appropriate UI feedback.
Transcript Loading (useTranscript.ts)
The useTranscript hook manages the state for fetching video transcripts. It maintains an error state string that is populated when the YoutubeService.fetchTranscript call fails.
The App.tsx component consumes this error state to render an alert banner with a "Retry" button.
Sources: hooks/useTranscript.ts:33-46, App.tsx:135-147
A notable feature is the Smart Fallback Logic. If fetching the transcript for the demo video fails (often due to network or CORS issues in local development), the hook loads a hardcoded demo transcript instead of showing a persistent error.
Sources: hooks/useTranscript.ts:37-42
Note Creation (useNotes.ts)
The useNotes hook handles errors during the creation of a margin note. It returns a structured object { success: boolean; reason?: string } to the caller, allowing for specific UI reactions.
The flowchart below shows the logic within the addNote function.
Sources: hooks/useNotes.ts:26-53, App.tsx:68-76
If addNote returns api_key_missing, the App.tsx component responds by opening the settings modal, prompting the user to enter their key.
Sources: App.tsx:68-72
AI Content Generation (useContentGenerator.ts)
To handle multiple, independent AI content generation tasks (e.g., Twitter thread, LinkedIn post), the useContentGenerator hook uses Promise.allSettled. This ensures that the failure of one generation does not prevent others from completing.
The progress state object tracks the status of each task ('loading', 'done', or 'error'). The UI can then reflect the status of each individual content piece, showing a loading spinner or an error indicator as needed.
// hooks/useContentGenerator.ts:114-120
// Run all generations in parallel
const [threadResult, linkedinResult, blogResult, takeawaysResult] = await Promise.allSettled([
generateTwitterThread(transcript),
generateLinkedInPost(transcript),
generateBlogOutline(transcript),
generateKeyTakeaways(transcript),
]);
If a promise is rejected, the corresponding property in the progress state is set to 'error', and the UI in SmartBoard.tsx can react accordingly, though the current implementation does not show a specific error message for these partial failures.
Sources: hooks/useContentGenerator.ts:114-149, components/SmartBoard.tsx:112-146
API Key Validation UI (Header.tsx)
The settings modal in the Header component provides direct feedback on API key validity. When the user clicks "Test Key", it calls validateApiKey and updates the keyStatus state to either 'valid' or 'invalid'. This state change triggers conditional rendering of a success checkmark or an error message next to the input field.
Sources: components/Header.tsx:143-149, components/Header.tsx:162-167
Summary
The application employs a layered error handling strategy that prioritizes resilience and user experience. The backend provides clear, specific error codes. Frontend services use a "fail-soft" approach to prevent crashes, while React hooks manage error states and drive the UI to display contextual feedback, such as toast notifications, inline alerts, and actionable prompts. This ensures that even when external services fail, the application remains stable and guides the user toward a resolution.