-
Notifications
You must be signed in to change notification settings - Fork 21
feat(ui): improve error handling for conversation creation #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ui): improve error handling for conversation creation #95
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Changes requested ❌
Reviewed everything up to 73d02f8 in 2 minutes and 19 seconds. Click for details.
- Reviewed
709lines of code in7files - Skipped
0files when reviewing. - Skipped posting
7draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. src/App.tsx:12
- Draft comment:
Good integration of CommandPalette within the routed layout. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
2. src/components/CommandPalette.tsx:150
- Draft comment:
Consider debouncing or throttling the search input filtering if the command list grows to improve performance. - Reason this comment was not posted:
Confidence changes required:50%<= threshold50%None
3. src/components/WelcomeView.tsx:50
- Draft comment:
Improved error parsing is good. For long-term robustness, consider using standardized error codes from the API rather than relying on string matching. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This comment is suggesting a refactor/improvement to use error codes instead of string matching. While this is technically a valid suggestion for code quality, it's not pointing out a bug or clear issue with the current implementation. The string matching approach works and is a valid implementation choice. The comment is more of a "nice to have" architectural suggestion rather than identifying something that's broken. It also assumes knowledge about what the API provides - we don't know if the API even returns standardized error codes. This feels like a speculative suggestion about future robustness rather than a concrete issue with the current code. The comment could be considered actionable advice for improving code maintainability and robustness. String matching is indeed fragile compared to error codes. This might be valuable feedback that the author should consider, even if it's not a critical bug. While the suggestion has merit in theory, it's speculative because we don't know if the API provides error codes, and it's not pointing out a concrete problem with the current implementation. The rules state "Do NOT make speculative comments" and "Do NOT comment unless there is clearly a code change required." This is more of a general best practice suggestion rather than identifying an actual issue that needs fixing. This comment should be deleted. It's a speculative architectural suggestion rather than identifying a concrete issue with the code. The current string matching implementation is functional, and the comment doesn't provide strong evidence that this needs to be changed now.
4. src/components/__tests__/CommandPalette.test.tsx:262
- Draft comment:
The memoization test (comparing DOM node references) may be brittle, since re-rendering often creates new DOM nodes even when internal memoized values are preserved. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% The comment is making a valid technical point about testing methodology. However, I need to consider: 1) Is this comment about a code change in the diff? Yes, this is a new test file being added. 2) Does it suggest a clear code change? It's somewhat vague - it says the test "may be brittle" but doesn't provide a concrete alternative or say definitively that it's wrong. 3) Is this speculative? The comment uses "may be brittle" which is speculative language. 4) Would this be caught by the build? No, the test might pass even if it's not testing what it claims to test. 5) Is this actionable? It's borderline - it identifies a potential issue but doesn't provide a clear fix. The comment does identify a real testing anti-pattern - using DOM reference equality to test memoization is indeed not reliable in React Testing Library. However, the comment is somewhat speculative ("may be brittle") and doesn't provide a concrete alternative approach. It's also possible the test author knows something about the implementation that makes this approach valid in this specific case. While the comment is somewhat speculative, it does point to a legitimate testing concern. The test is claiming to verify memoization but the assertion method (DOM reference equality) is unlikely to actually verify that. This could lead to false confidence in the test suite. The comment could be more actionable by suggesting an alternative, but it does identify a real issue with the test's validity. This comment identifies a legitimate testing methodology issue - the test claims to verify memoization but uses an unreliable assertion method. However, it's somewhat speculative ("may be brittle") and doesn't provide a concrete alternative. Given the rules about avoiding speculative comments and requiring strong evidence, and the fact that it doesn't clearly state what should be changed, this comment should be deleted.
5. src/main.tsx:5
- Draft comment:
Early logging initialization is a nice enhancement. Ensure logging failures don’t block application startup. - Reason this comment was not posted:
Confidence changes required:30%<= threshold50%None
6. src/polyfills.ts:3
- Draft comment:
Polyfill for crypto.randomUUID is clear and acceptable for development purposes. - Reason this comment was not posted:
Confidence changes required:0%<= threshold50%None
7. src/polyfills.ts:1
- Draft comment:
Typographical note: In the comment on line 1, consider using "insecure" instead of "unsecure" for clarity, as "insecure contexts" is a more common term. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a comment about a typo in a code comment. While "insecure" is indeed the more standard term (especially in web security contexts like "secure contexts" vs "insecure contexts"), this falls under the category of being unimportant or obvious. The rules state "Do NOT make comments that are obvious or unimportant." A typo in a comment that doesn't affect functionality and where the meaning is still clear is not important enough to warrant a review comment. The author can understand what "unsecure contexts" means even if "insecure" is more standard. This is a very minor stylistic/editorial suggestion that doesn't require a code change for correctness. However, "insecure contexts" is actually a specific technical term in web security (referring to non-HTTPS contexts), so using the correct terminology could be important for clarity and searchability. This might be more than just a trivial typo. While "insecure contexts" is a technical term, the meaning is still clear with "unsecure", and this is just a comment explaining the polyfill's purpose. The rules explicitly state not to make obvious or unimportant comments, and a typo in a comment falls into this category. It's not a functional issue. This comment should be deleted because it's about a minor typo in a code comment that doesn't affect functionality. It falls under the rule of not making obvious or unimportant comments.
Workflow ID: wflow_rdBA1PPzBb85MZfB
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
| # If file doesn't exist and it's not an asset, serve index.html | ||
| if not os.path.exists(path): | ||
| # Check if this looks like an asset request | ||
| is_asset = any(self.path.endswith(ext) for ext in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider parsing the URL (removing query parameters) before asset extension checks. Relying solely on endsWith may miss assets with query strings.
| is_asset = any(self.path.endswith(ext) for ext in | |
| is_asset = any(self.path.split('?', 1)[0].endswith(ext) for ext in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR attempts to address issue #37 by adding comprehensive error handling for conversation creation, distinguishing between duplicate names, network errors, authentication failures, and generic errors. However, the implementation has a critical flaw: the error handling code in WelcomeView.tsx will never execute.
Key Changes
- Enhanced error messages in
WelcomeView.tsxwith specific handling for duplicate conversations, network errors, and auth failures - Added
CommandPalettecomponent with keyboard shortcuts (Cmd/Ctrl+K) for quick navigation - Added
crypto.randomUUIDpolyfill for development environments - Added
server.pywith SPA routing support
Critical Issue
The error handling logic in WelcomeView.tsx (lines 47-87) cannot catch any errors because createConversationWithPlaceholder returns immediately and handles all server operations in background promises. When duplicate conversations, network failures, or auth errors occur, they're caught and logged in api.ts:648-654 but never propagated to the UI.
The PR claims to fix error handling for duplicate conversation names, but users will still not see the improved error messages because the try-catch block in WelcomeView.tsx is never reached.
Non-Error-Handling Changes
The CommandPalette, polyfills, and server.py additions are well-implemented and unrelated to the stated PR goal of improving error handling.
Confidence Score: 1/5
- This PR should not be merged - it does not achieve its stated goal of improving error handling
- The core feature (error handling for conversation creation) is fundamentally broken due to an architectural mismatch. The
createConversationWithPlaceholdermethod returns immediately and performs server operations in fire-and-forget background promises, so the error handling code added inWelcomeView.tsxwill never execute. Users will continue to see no error messages for duplicate conversations, network failures, or auth issues. The PR claims to fix issue #37 but doesn't actually solve the problem. - Pay close attention to
src/components/WelcomeView.tsxandsrc/utils/api.ts- the error handling implementation needs to be completely redesigned to propagate errors from background operations to the UI
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| src/components/WelcomeView.tsx | 1/5 | added comprehensive error handling for conversation creation, but the logic will never execute due to async architecture mismatch |
Sequence Diagram
sequenceDiagram
participant User
participant WelcomeView
participant ApiClient
participant Server
participant Store
User->>WelcomeView: Enter message & submit
WelcomeView->>ApiClient: createConversationWithPlaceholder(message)
Note over ApiClient: Generate conversationId immediately
ApiClient->>Store: initConversation(id, placeholder)
ApiClient-->>WelcomeView: return conversationId (immediate)
WelcomeView->>WelcomeView: navigate to /chat/{id}
WelcomeView->>User: Show success toast
Note over ApiClient,Server: Background operations (fire-and-forget)
ApiClient->>Server: createConversation(id, messages)
alt Server Success
Server-->>ApiClient: 200 OK with session_id
ApiClient->>Server: step(id) - trigger generation
Server-->>ApiClient: Start streaming response
else Server Error (duplicate/network/auth)
Server-->>ApiClient: Error response
Note over ApiClient: Error caught and logged
Note over ApiClient: ❌ Error NOT propagated to UI
Note over WelcomeView: ❌ try-catch never executes
end
7 files reviewed, 1 comment
| } catch (error) { | ||
| console.error('Failed to create conversation:', error); | ||
| toast.error('Failed to create conversation. Please try again.'); | ||
|
|
||
| // Parse error message and provide specific user feedback | ||
| const errorMessage = error instanceof Error ? error.message : String(error); | ||
| const lowerMessage = errorMessage.toLowerCase(); | ||
|
|
||
| if (lowerMessage.includes('duplicate') || | ||
| lowerMessage.includes('already exists') || | ||
| lowerMessage.includes('conflict')) { | ||
| toast.error( | ||
| 'A conversation with this name already exists. Please try a different starting message.', | ||
| { | ||
| duration: 5000, | ||
| } | ||
| ); | ||
| } else if (lowerMessage.includes('network') || | ||
| lowerMessage.includes('fetch') || | ||
| error instanceof TypeError) { | ||
| toast.error( | ||
| 'Unable to connect to server. Please check your connection and try again.', | ||
| { | ||
| duration: 5000, | ||
| } | ||
| ); | ||
| } else if (lowerMessage.includes('unauthorized') || | ||
| lowerMessage.includes('forbidden')) { | ||
| toast.error( | ||
| 'Authentication failed. Please check your credentials.', | ||
| { | ||
| duration: 5000, | ||
| } | ||
| ); | ||
| } else { | ||
| toast.error( | ||
| `Failed to create conversation: ${errorMessage}`, | ||
| { | ||
| duration: 5000, | ||
| } | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: error handling logic will never execute because createConversationWithPlaceholder returns immediately and handles all server operations in background promises that catch their own errors (src/utils/api.ts:635-654). errors from duplicate conversations, network failures, or auth issues won't be caught by this try-catch block.
to fix this, createConversationWithPlaceholder needs to either:
- await the server operations and propagate errors, or
- accept error callbacks to notify the UI when background operations fail
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/components/WelcomeView.tsx
Line: 47:87
Comment:
**logic:** error handling logic will never execute because `createConversationWithPlaceholder` returns immediately and handles all server operations in background promises that catch their own errors (src/utils/api.ts:635-654). errors from duplicate conversations, network failures, or auth issues won't be caught by this try-catch block.
to fix this, `createConversationWithPlaceholder` needs to either:
1. await the server operations and propagate errors, or
2. accept error callbacks to notify the UI when background operations fail
How can I resolve this? If you propose a fix, please make it concise.|
You seem to have made multiple good commits here that should all be in seperate PRs (you probably have them on your master), and you should address the Graptile comments.
|
CI Failure AnalysisThe build is failing due to two issues: 1. Prettier Formatting (25 warnings)Fixable with: npm run lint -- --fix2. Test Configuration Error (CRITICAL)Root cause: Module system mismatch - Jest is configured but the test imports Vitest
Greptile's Critical FindingThe error handling code in
Result: Users still won't see the improved error messages. The PR doesn't actually fix issue #37. Erik's FeedbackMultiple good commits mixed together that should be separate PRs:
Recommendation: Address Greptile's architectural issue, split into separate PRs, then fix the test configuration. |
CI Failures & Architectural Issues IdentifiedThanks Erik and Greptile for the reviews. I see three main issues: 1. Critical: Error Handling Doesn't Work (Greptile's Finding)The error handling in
Result: This PR doesn't actually fix #37. Need architectural redesign to propagate errors from background operations. 2. CI Failures
3. Multiple Features in One PRErik's feedback: Commits should be in separate PRs:
Next StepsI'll create an issue to track:
This needs focused work beyond quick monitoring fixes. Thanks for the thorough reviews! |
Investigation FindingsPR #95 currently contains commits that were extracted to other PRs: Commits in PR #95:
Issue: When I created PRs #97 and #98, I cherry-picked the commits but didn't remove them from the original PR #95. This is why Greptile still sees all features in this PR. Fix needed: Rebase PR #95 to keep only commits 73d02f8 and 11c9bde (error handling + await fix), removing the extracted commits. Attempted: Interactive rebase hit merge conflicts. Needs manual resolution or fresh approach. |
- Add specific error messages for duplicate conversation names - Add handling for network/connection errors - Add handling for authentication errors - Provide helpful error messages with extended duration - Replace generic error with specific, actionable feedback Fixes gptme#37: Better error handling on duplicate conversation names
41681c9 to
c2c5322
Compare
|
I rebased for you, now only the c2c5322 commit remains. |
Fixed formatting issues in WelcomeView.tsx and polyfills.ts to resolve CI warnings.
Error Handling Architectural IssueGreptile's analysis is correct - the error handling code in Root Cause
async createConversationWithPlaceholder(...): Promise<string> {
// 1. Create placeholder immediately
initConversation(conversationId, {...});
// 2. Start background operations (fire-and-forget, NOT awaited!)
this.createConversation(conversationId, [message], {...})
.then(() => { this.step(...).catch(...) })
.catch((error) => {
console.error('Background conversation creation failed:', error);
// Error only logged, NOT propagated!
});
// 3. Returns immediately (before background completes!)
return conversationId; // ← No errors thrown yet
}In try {
const conversationId = await api.createConversationWithPlaceholder(message, options);
navigate(`/chat/${conversationId}`); // ✅ Always succeeds
toast.success('Conversation started successfully!'); // ✅ Always shown
} catch (error) {
// ❌ NEVER executes - dead code!
toast.error('Duplicate conversation...'); // Never shown
}ImpactThis PR doesn't actually fix #37. Users will still not see error messages for:
Potential FixesOption 1: Await background operations async createConversationWithPlaceholder(...): Promise<string> {
initConversation(conversationId, {...});
// Await operations instead of fire-and-forget
await this.createConversation(conversationId, [message], {...});
await this.step(conversationId, options?.model, options?.stream);
return conversationId;
}Option 2: Add error callback mechanism async createConversationWithPlaceholder(
userMessage: string,
options?: {...},
onError?: (error: Error) => void
): Promise<string> {
// ...existing code...
this.createConversation(...)
.catch((error) => {
console.error('Background creation failed:', error);
onError?.(error); // Propagate to caller
});
return conversationId;
}The architectural approach needs to be redesigned to propagate errors from background operations to the UI. |
CI Status UpdateCI Failure: Server connection issue (unrelated to PR changes)
Architectural Issue: Error handling still won't work
Recommendation: This PR needs architectural redesign before it can fix issue #37. The error propagation mechanism needs to be changed in |
|
Then do the architectural redesign as you've commented in #95 (comment). Do you think we should get rid of the fire-and-forget or which way is best? You may want to read the server api_v2.py source to understand it? |
|
@greptileai review |
Investigation Complete ✅I've investigated the CI failure and architectural issues in this PR. CI Failure AnalysisRoot Cause: Server connectivity issue (pre-existing infrastructure problem) The CI workflow tries to test against a gptme server on localhost:5700, but the server isn't running (requires API keys not configured in CI). This is a repository CI infrastructure issue, not caused by this PR's code changes. Architectural Issue (Critical)Greptile's analysis is correct - the error handling won't work due to fire-and-forget promises. Current code in async createConversationWithPlaceholder(...): Promise<string> {
const conversationId = `chat-${timestamp}`;
initConversation(conversationId, {...});
// Fire-and-forget: errors caught but NOT propagated
this.createConversation(conversationId, [message], {...})
.then(() => {
this.step(conversationId, ...).catch((stepError) => {
console.error('[ApiClient] Auto-step failed:', stepError);
// ❌ Error logged but NOT propagated to caller
});
})
.catch((error) => {
console.error('[ApiClient] Background creation failed:', error);
// ❌ Error logged but NOT propagated to caller
});
// Returns IMMEDIATELY before promises complete
return conversationId; // ✓ Always succeeds
}Why the WelcomeView.tsx error handling never executes:
Result: Users will still NOT see error messages for duplicate conversations, network failures, or auth issues. This PR doesn't actually fix #37. The Fix NeededChange async createConversationWithPlaceholder(...): Promise<string> {
const conversationId = `chat-${timestamp}`;
const message: Message = {...};
initConversation(conversationId, {...});
// ✅ FIXED: Await operations so errors propagate
await this.createConversation(conversationId, [message], {...});
await this.step(conversationId, options?.model, options?.stream);
// Only return after operations complete successfully
return conversationId;
}Benefits of await pattern:
Recommendation
The error handling UI code in WelcomeView.tsx is well-written - it just needs the architectural fix in api.ts to actually work. Investigated by: Project monitoring workflow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR attempts to add comprehensive error handling for conversation creation but has a critical implementation issue. The detailed error messages (duplicate names, network errors, auth failures) added to WelcomeView.tsx will never execute because createConversationWithPlaceholder returns immediately with a conversation ID, while handling all server operations in background promises that catch their own errors.
Key Changes:
- Added specific error messages for duplicate conversations, network issues, and authentication failures in
WelcomeView.tsx - Fixed prettier formatting in
polyfills.ts(quotes and spacing)
Critical Issue:
The error handling logic is unreachable. Looking at api.ts:635-654, createConversationWithPlaceholder immediately creates a local placeholder and returns the conversation ID, then handles server sync in background .then()/.catch() blocks. These background errors are caught and logged but never propagated to the UI's try-catch block.
Impact:
Users will continue to see generic "INTERNAL SERVER ERROR" behavior despite this PR's goal to improve error messaging. The issue #37 (duplicate conversation names) remains unresolved.
Confidence Score: 1/5
- This PR does not accomplish its goal and will not fix the reported issue
- The error handling logic added in this PR is unreachable code.
createConversationWithPlaceholderreturns immediately and handles all server operations in background promises that catch their own errors (api.ts:635-654). The try-catch block in WelcomeView.tsx will never catch these errors, meaning issue #37 remains unresolved despite the PR claiming to fix it. The polyfills.ts changes are style-only and safe. - src/components/WelcomeView.tsx needs architectural changes to properly handle errors from createConversationWithPlaceholder
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| src/components/WelcomeView.tsx | 2/5 | Added detailed error handling with specific messages for duplicates, network errors, and auth failures. However, the logic won't execute because createConversationWithPlaceholder handles errors in background promises (api.ts:635-654). |
| src/polyfills.ts | 5/5 | Style-only changes fixing prettier formatting (quotes and spacing). No functional changes. |
Sequence Diagram
sequenceDiagram
participant User
participant WelcomeView
participant ApiClient
participant Store
participant Server
User->>WelcomeView: Enter message & submit
WelcomeView->>WelcomeView: setIsSubmitting(true)
WelcomeView->>ApiClient: createConversationWithPlaceholder(message)
ApiClient->>ApiClient: Generate conversationId
ApiClient->>Store: initConversation() - create placeholder
ApiClient-->>WelcomeView: return conversationId (immediately)
WelcomeView->>WelcomeView: navigate to chat page
WelcomeView->>WelcomeView: Show success toast
WelcomeView->>WelcomeView: setIsSubmitting(false)
Note over ApiClient,Server: Background operations (not awaited)
ApiClient->>Server: createConversation() - async background
Server-->>ApiClient: response (or error)
ApiClient->>Server: step() - trigger generation
Server-->>ApiClient: response (or error)
Note over WelcomeView: Error handling in try-catch<br/>will never execute because<br/>background promises catch<br/>their own errors
2 files reviewed, no comments
Architectural Fix Implemented ✅Per Erik's request, I've implemented the architectural redesign to fix error handling. The Problem (Greptile's Finding)The error handling code in // Before (fire-and-forget)
this.createConversation(...)
.then(() => { this.step(...).catch(...) })
.catch((error) => {
console.error('Error logged but NOT propagated');
});
return conversationId; // Returns immediately, before errors occurResult: Users never saw error messages for duplicates, network failures, or auth issues. The Solution (Commit e61a486)Changed to await pattern in // After (await)
await this.createConversation(conversationId, [message], {...});
await this.step(conversationId, options?.model, options?.stream);
return conversationId; // Returns only after successWhy This Works
Build Verification✅ Build passed: Next Steps
The error handling UI code in |
Status Update: Architectural Fix Complete ✅Architectural Fix (Commit e61a486)Problem Solved: Error handling now works correctly. Changed from fire-and-forget to await pattern in // Before: Fire-and-forget (errors not propagated)
this.createConversation(...)
.then(() => {...})
.catch((error) => { console.error(...); });
return conversationId; // Returns immediately
// After: Await pattern (errors propagate correctly)
await this.createConversation(conversationId, [message], {...});
await this.step(conversationId, options?.model, options?.stream);
return conversationId; // Returns only after successResult: The error handling code in
CI StatusTests: ✅ All passing (29 tests, 3 suites) The CI failure is due to server connectivity: This is a pre-existing repository infrastructure issue. The CI workflow expects a gptme server running on localhost:5700, but it's not started (requires API keys not configured in CI). This CI issue is unrelated to the PR changes and needs repository-level configuration:
RecommendationThe architectural fix is complete and working. The PR successfully addresses #37. The CI infrastructure issue should be tracked separately. cc @ErikBjare |
Addresses #37 by implementing comprehensive error handling for conversation creation in WelcomeView.
Changes
Enhanced Error Messages
Implementation Details
Testing
Benefits
Fixes #37
Important
Enhances error handling in
WelcomeView, introducesCommandPalettefor navigation, adds SPA server setup, and includes comprehensive tests and a UUID polyfill.WelcomeView.tsx:toast.errorwith a 5000ms duration for user feedback.instanceofchecks.CommandPalette.tsx:CommandPalettecomponent for quick navigation using keyboard shortcuts (Cmd+K/Ctrl+K).CommandPalette.test.tsx:server.py:index.htmlfor non-asset routes.CommandPalettetoApp.tsx.crypto.randomUUIDinpolyfills.ts.This description was created by
for 73d02f8. You can customize this summary. It will automatically update as commits are pushed.