Skip to content

Commit 13380c5

Browse files
committed
feat: clear error messaging with upgrade prompts
- Fix [object Object] error in DashboardHome.tsx (was showing raw object instead of message) - Add extractErrorMessage() helper for proper API error extraction - Add isUpgradeError() to detect REPO_TOO_LARGE/REPO_LIMIT_REACHED - Show toast with 'Join Waitlist' action button on limit errors - Reuse WaitlistModal for upgrade flow (no new components) - Add 'repos' to SKIP_DIRS in repo_validator.py (skip cloned repos)
1 parent 7a4e5bf commit 13380c5

2 files changed

Lines changed: 59 additions & 4 deletions

File tree

backend/services/repo_validator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class RepoValidator:
100100
'.ruff_cache',
101101
'egg-info',
102102
'.eggs',
103+
'repos', # Cloned repositories (CodeIntel internal)
103104
}
104105

105106
# Average functions per file by language (rough estimates)

frontend/src/components/dashboard/DashboardHome.tsx

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,27 @@ import { StyleInsights } from '../StyleInsights'
2626
import { ImpactAnalyzer } from '../ImpactAnalyzer'
2727
import { DashboardStats } from './DashboardStats'
2828
import { IndexingProgressModal } from '../IndexingProgressModal'
29+
import { WaitlistModal } from '../landing/WaitlistModal'
2930
import type { Repository } from '../../types'
3031
import type { GitHubRepo } from '../../hooks/useGitHubRepos'
3132
import { API_URL } from '../../config/api'
3233

3334
const MAX_FREE_REPOS = 3
3435

36+
// Extract error message from API response (handles nested detail objects)
37+
function extractErrorMessage(err: any, fallback: string): string {
38+
if (typeof err?.detail === 'string') return err.detail
39+
if (err?.detail?.message) return err.detail.message
40+
if (err?.message) return err.message
41+
return fallback
42+
}
43+
44+
// Check if error is a limit/upgrade error
45+
function isUpgradeError(err: any): boolean {
46+
const code = err?.detail?.error || err?.detail?.error_code
47+
return ['REPO_TOO_LARGE', 'REPO_LIMIT_REACHED'].includes(code)
48+
}
49+
3550
type RepoTab = 'overview' | 'search' | 'dependencies' | 'insights' | 'impact'
3651

3752
export function DashboardHome() {
@@ -49,6 +64,9 @@ export function DashboardHome() {
4964
const [indexingRepoId, setIndexingRepoId] = useState<string | null>(null)
5065
const [indexingRepoName, setIndexingRepoName] = useState<string>('')
5166
const [showIndexingModal, setShowIndexingModal] = useState(false)
67+
68+
// Upgrade prompt modal state
69+
const [showUpgradeModal, setShowUpgradeModal] = useState(false)
5270

5371
// Auto-open GitHub import modal if redirected from OAuth callback
5472
useEffect(() => {
@@ -96,7 +114,14 @@ export function DashboardHome() {
96114

97115
if (!response.ok) {
98116
const err = await response.json().catch(() => ({}))
99-
throw new Error(err.detail || 'Failed to add repository')
117+
if (isUpgradeError(err)) {
118+
toast.error(extractErrorMessage(err, 'Repository too large'), {
119+
description: 'Join the Pro waitlist for higher limits',
120+
action: { label: 'Join Waitlist', onClick: () => setShowUpgradeModal(true) }
121+
})
122+
return
123+
}
124+
throw new Error(extractErrorMessage(err, 'Failed to add repository'))
100125
}
101126

102127
const data = await response.json()
@@ -110,7 +135,14 @@ export function DashboardHome() {
110135

111136
if (!indexResponse.ok) {
112137
const err = await indexResponse.json().catch(() => ({}))
113-
throw new Error(err.detail?.message || err.detail || 'Failed to start indexing')
138+
if (isUpgradeError(err)) {
139+
toast.error(extractErrorMessage(err, 'Repository too large'), {
140+
description: 'Join the Pro waitlist for higher limits',
141+
action: { label: 'Join Waitlist', onClick: () => setShowUpgradeModal(true) }
142+
})
143+
return
144+
}
145+
throw new Error(extractErrorMessage(err, 'Failed to start indexing'))
114146
}
115147

116148
// Show indexing progress modal
@@ -150,7 +182,14 @@ export function DashboardHome() {
150182

151183
if (!response.ok) {
152184
const err = await response.json().catch(() => ({}))
153-
throw new Error(err.detail || `Failed to add ${repo.name}`)
185+
if (isUpgradeError(err)) {
186+
toast.error(extractErrorMessage(err, `${repo.name} too large`), {
187+
description: 'Join the Pro waitlist for higher limits',
188+
action: { label: 'Join Waitlist', onClick: () => setShowUpgradeModal(true) }
189+
})
190+
continue
191+
}
192+
throw new Error(extractErrorMessage(err, `Failed to add ${repo.name}`))
154193
}
155194

156195
const data = await response.json()
@@ -164,7 +203,14 @@ export function DashboardHome() {
164203

165204
if (!indexResponse.ok) {
166205
const err = await indexResponse.json().catch(() => ({}))
167-
const errMsg = err.detail?.message || err.detail || 'Indexing failed to start'
206+
if (isUpgradeError(err)) {
207+
toast.error(extractErrorMessage(err, `${repo.name} too large`), {
208+
description: 'Join the Pro waitlist for higher limits',
209+
action: { label: 'Join Waitlist', onClick: () => setShowUpgradeModal(true) }
210+
})
211+
continue
212+
}
213+
const errMsg = extractErrorMessage(err, 'Indexing failed to start')
168214
console.error(`Failed to start indexing for ${repo.name}:`, err)
169215
toast.warning(`${repo.name} added but indexing failed`, {
170216
description: errMsg
@@ -439,6 +485,14 @@ export function DashboardHome() {
439485
maxSelectable={MAX_FREE_REPOS}
440486
currentRepoCount={repos.length}
441487
/>
488+
489+
{/* Upgrade/Waitlist Modal */}
490+
<WaitlistModal
491+
isOpen={showUpgradeModal}
492+
onClose={() => setShowUpgradeModal(false)}
493+
planName="Pro"
494+
planPrice="$19/mo"
495+
/>
442496
</div>
443497
)
444498
}

0 commit comments

Comments
 (0)