Skip to content

Commit aa32694

Browse files
authored
Merge pull request #399 from unoplat/enhancement-improved-error-messages
fix: improved error messages
2 parents b94d4fa + 7cbc434 commit aa32694

File tree

3 files changed

+118
-13
lines changed
  • unoplat-code-confluence-frontend/src/pages
  • unoplat-code-confluence-ingestion/code-confluence-flow-bridge

3 files changed

+118
-13
lines changed

unoplat-code-confluence-frontend/src/pages/OnboardingPage.tsx

Lines changed: 116 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from '@tanstack/react-table';
88
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '../components/ui/card';
99
import { Button } from '../components/ui/button';
10-
import { fetchGitHubRepositories, submitRepositories } from '../lib/api';
10+
import { fetchGitHubRepositories, submitRepositories, ApiError } from '../lib/api';
1111
import { useToast } from '../components/ui/use-toast';
1212
import { RepositoryTable } from '../components/RepositoryTable';
1313

@@ -33,6 +33,66 @@ export default function OnboardingPage(): React.ReactElement {
3333
enabled: true, // Fetch automatically when component mounts
3434
});
3535

36+
// Get appropriate error message based on error details
37+
const getErrorMessage = (): { title: string; message: string; action: string } => {
38+
// Safely cast error to ApiError, ensuring it's actually an ApiError type
39+
if (!error) {
40+
return {
41+
title: 'Unknown Error',
42+
message: 'An unexpected error occurred.',
43+
action: 'Please try refreshing the page.'
44+
};
45+
}
46+
47+
// Check if error is an ApiError by checking for the isAxiosError property
48+
const apiError = error as unknown as ApiError;
49+
const isApiError = apiError && 'isAxiosError' in apiError;
50+
51+
// If it's not an ApiError, provide a default error message
52+
if (!isApiError) {
53+
return {
54+
title: 'Error Fetching Repositories',
55+
message: error instanceof Error ? error.message : 'Unknown error occurred',
56+
action: 'Please try refreshing the page.'
57+
};
58+
}
59+
60+
const statusCode = apiError.statusCode;
61+
const errorMessage = apiError.message || 'Unknown error occurred';
62+
63+
// Default error info
64+
let title = 'Error Fetching Repositories';
65+
let message = 'We encountered an issue while trying to fetch your repositories.';
66+
let action = 'Please try refreshing the page.';
67+
68+
// Handle specific error cases
69+
if (statusCode === 404) {
70+
title = 'GitHub Credentials Missing';
71+
message = 'We couldn\'t find your GitHub credentials in our system.';
72+
action = 'Please set up your GitHub token first.';
73+
} else if (statusCode === 401 || (errorMessage && errorMessage.includes('token'))) {
74+
title = 'Authentication Error';
75+
message = 'Your GitHub token may have expired or doesn\'t have the necessary permissions.';
76+
action = 'Please update your GitHub toke from settings page with appropriate permissions.';
77+
} else if (statusCode === 500) {
78+
if (errorMessage.includes('decryption')) {
79+
title = 'Token Decryption Error';
80+
message = 'We had trouble decrypting your GitHub token.';
81+
action = 'Please try setting up your token again.';
82+
} else if (errorMessage.includes('GitHub API error')) {
83+
title = 'GitHub API Error';
84+
message = 'GitHub API returned an error while fetching your repositories.';
85+
action = 'Please check your GitHub account status and try again later.';
86+
} else if (errorMessage.includes('Database error')) {
87+
title = 'System Error';
88+
message = 'We encountered a database issue while accessing your credentials.';
89+
action = 'Please try again later. If the problem persists, contact support.';
90+
}
91+
}
92+
93+
return { title, message, action };
94+
};
95+
3696
// Function to handle submitting selected repositories
3797
const handleSubmitSelections = async (): Promise<void> => {
3898
try {
@@ -68,6 +128,18 @@ export default function OnboardingPage(): React.ReactElement {
68128
}
69129
};
70130

131+
// Route to token setup page
132+
const goToTokenSetup = (): void => {
133+
window.location.href = '/setup';
134+
};
135+
136+
// Function to safely check if an error is an ApiError with the specified status
137+
const isApiErrorWithStatus = (statusCode: number): boolean => {
138+
if (!error) return false;
139+
const apiError = error as unknown as ApiError;
140+
return 'isAxiosError' in apiError && apiError.statusCode === statusCode;
141+
};
142+
71143
return (
72144
<div className="container mx-auto py-8">
73145
<h1 className="text-3xl font-bold tracking-tight mb-6">GitHub Repository Selection</h1>
@@ -90,11 +162,35 @@ export default function OnboardingPage(): React.ReactElement {
90162

91163
{error && (
92164
<div className="bg-destructive/10 border-l-4 border-destructive p-4 mb-4 rounded">
93-
<div className="flex">
165+
<div className="flex flex-col">
94166
<div className="ml-3">
95-
<p className="text-sm text-destructive">
96-
Failed to fetch repositories. Please try refreshing the page.
167+
<h3 className="text-sm font-medium text-destructive">
168+
{getErrorMessage().title}
169+
</h3>
170+
<p className="text-sm text-destructive/90 mt-1">
171+
{getErrorMessage().message}
172+
</p>
173+
<p className="text-sm text-destructive/80 mt-2">
174+
{getErrorMessage().action}
97175
</p>
176+
<div className="mt-3 flex flex-row gap-2">
177+
<Button
178+
variant="outline"
179+
onClick={() => refetch()}
180+
size="sm"
181+
>
182+
Try Again
183+
</Button>
184+
{isApiErrorWithStatus(404) && (
185+
<Button
186+
variant="default"
187+
onClick={goToTokenSetup}
188+
size="sm"
189+
>
190+
Set Up GitHub Token
191+
</Button>
192+
)}
193+
</div>
98194
</div>
99195
</div>
100196
</div>
@@ -134,13 +230,22 @@ export default function OnboardingPage(): React.ReactElement {
134230
<p className="text-sm text-amber-700">
135231
No repositories found. This could be because your GitHub token doesn't have the necessary permissions.
136232
</p>
137-
<Button
138-
variant="ghost"
139-
onClick={() => refetch()}
140-
className="mt-2"
141-
>
142-
Try refreshing
143-
</Button>
233+
<div className="mt-2 flex gap-2">
234+
<Button
235+
variant="ghost"
236+
onClick={() => refetch()}
237+
size="sm"
238+
>
239+
Try refreshing
240+
</Button>
241+
<Button
242+
variant="outline"
243+
onClick={goToTokenSetup}
244+
size="sm"
245+
>
246+
Update GitHub Token
247+
</Button>
248+
</div>
144249
</div>
145250
</div>
146251
</div>

unoplat-code-confluence-ingestion/code-confluence-flow-bridge/src/code_confluence_flow_bridge/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ async def get_repos(session: Session = Depends(get_session)) -> List[GitHubRepoS
205205
response = await client.get("https://api.github.com/user/repos?visibility=all&per_page=100&page=1", headers=headers)
206206
if response.status_code != 200:
207207
logger.error(f"GitHub API error: {response.text}")
208-
raise HTTPException(status_code=response.status_code, detail="GitHub API error: failed to fetch repositories")
208+
raise HTTPException(status_code=500, detail=f"GitHub API error: failed to fetch repositories {response.text}")
209209

210210
repos_data = response.json()
211211

unoplat-code-confluence-ingestion/code-confluence-flow-bridge/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)