Problem
When enabling webhooks in project settings, error handling discards backend diagnostic information and shows only generic messages. When the enable-webhook request or auto-setup fails, manual webhook setup instructions are not shown at all.
Current Behavior
There are two failure scenarios, both with UX problems:
Scenario A — The PATCH to toggle webhooks_enabled itself fails (line 2096 catch):
This is the scenario triggered by the "Failed to update webhook settings" error. The state flow:
githubIntegrationApi.update() throws
- Outer catch fires →
setError("Failed to update webhook settings")
onIntegrationUpdate was never called → githubIntegration.webhooks_enabled stays false
- The entire webhook content section gated by
{githubIntegration.webhooks_enabled && ( at line 2150 does not render
showManualSetup is false (line 2124 requires webhooks_enabled to be true)
- The setTimeout auto-setup never runs — we hit the catch before reaching it
- Result: user sees only "Failed to update webhook settings" with no manual setup option and no way forward
Scenario B — The PATCH succeeds but setupWebhook auto-setup fails (line 2090 catch):
githubIntegrationApi.update() succeeds → webhooks_enabled = true
- setTimeout fires →
setupWebhook() throws
- Catch sets
webhookStatus = "unknown" with no error message
showManualSetup is true, "Show manual setup details" button renders
- But there is no visual indication that something failed — no error, no warning badge
- Result: user sees the toggle as enabled but gets no feedback about the failure, must discover the setup button on their own
Error Information Available but Discarded
The ApiError class carries the full backend response in message (parsed from response.text() at client.ts:57-58). The backend returns JSON like {"detail": "GitHub token lacks 'admin:repo_hook' scope"}. All three catch blocks discard this:
| Catch block |
Line |
Current message |
Backend detail discarded |
handleToggleWebhooks |
2096 |
"Failed to update webhook settings" |
Yes |
| Auto-setup after toggle |
2090 |
(no message at all) |
Yes |
runWebhookSetup retry |
2052 |
"Failed to setup webhook." |
Yes |
Proposed Fix
1. Extract and display backend error details
In all three catch blocks, extract the detail from ApiError:
} catch (err) {
let detail = "Failed to update webhook settings";
if (err instanceof ApiError) {
try {
const body = JSON.parse(err.message);
detail = body.detail || err.message;
} catch {
detail = err.message || detail;
}
}
setError(detail);
}
2. Add expandable error detail UI
Replace the plain error <p> with a collapsible detail:
⚠ Failed to update webhook settings [Show details ▾]
└─ "GitHub App token does not have 'admin:repo_hook' scope.
Use manual webhook setup instead."
This could be a simple <details>/<summary> element or a "Show details" toggle.
3. Show manual setup when the PATCH fails (Scenario A)
When the update() PATCH fails, the manual setup section is completely hidden because webhooks_enabled remains false. The fix should show manual setup instructions alongside the error even when the toggle PATCH failed:
- Either: decouple the manual setup UI from
webhooks_enabled — show it whenever there's a webhook-related error
- Or: add a "Set up webhook manually instead" link/button next to the error message that reveals the manual setup section regardless of toggle state
4. Auto-reveal manual setup on auto-setup failure (Scenario B)
When the auto-setup catch fires (line 2090-2092), set webhookStatus to "error" (not "unknown") so that:
- The retry button is visible (
webhookStatus !== "unknown" is true)
- An error message is shown (currently none)
- Ideally also trigger
handleRevealSecret() to auto-reveal the URL/secret/instructions
5. Show webhook status message for non-success states
The webhookMessage from setupWebhook response includes useful info for no_scope, no_token, and manual_required statuses, but should be visually distinguished for error-like states (e.g. red/amber styling for error/no_scope/no_token).
Affected Code
| Location |
Line |
Issue |
handleToggleWebhooks catch |
settings/page.tsx:2096 |
Generic error, discards ApiError.message, no manual setup shown |
| Auto-setup catch after toggle |
settings/page.tsx:2090 |
Silent failure, no error shown, sets status to "unknown" instead of "error" |
runWebhookSetup catch |
settings/page.tsx:2052 |
Generic error, discards ApiError.message |
| Webhook content gate |
settings/page.tsx:2150 |
Entire section hidden when webhooks_enabled is false |
showManualSetup logic |
settings/page.tsx:2124 |
Requires webhooks_enabled to be true — no manual fallback when PATCH fails |
| Error display |
settings/page.tsx:2276 |
Plain text, no expandable detail, no link to manual setup |
Acceptance Criteria
Problem
When enabling webhooks in project settings, error handling discards backend diagnostic information and shows only generic messages. When the enable-webhook request or auto-setup fails, manual webhook setup instructions are not shown at all.
Current Behavior
There are two failure scenarios, both with UX problems:
Scenario A — The PATCH to toggle
webhooks_enableditself fails (line 2096 catch):This is the scenario triggered by the "Failed to update webhook settings" error. The state flow:
githubIntegrationApi.update()throwssetError("Failed to update webhook settings")onIntegrationUpdatewas never called →githubIntegration.webhooks_enabledstaysfalse{githubIntegration.webhooks_enabled && (at line 2150 does not rendershowManualSetupisfalse(line 2124 requireswebhooks_enabledto be true)Scenario B — The PATCH succeeds but
setupWebhookauto-setup fails (line 2090 catch):githubIntegrationApi.update()succeeds →webhooks_enabled = truesetupWebhook()throwswebhookStatus = "unknown"with no error messageshowManualSetupistrue, "Show manual setup details" button rendersError Information Available but Discarded
The
ApiErrorclass carries the full backend response inmessage(parsed fromresponse.text()atclient.ts:57-58). The backend returns JSON like{"detail": "GitHub token lacks 'admin:repo_hook' scope"}. All three catch blocks discard this:handleToggleWebhooks"Failed to update webhook settings"runWebhookSetupretry"Failed to setup webhook."Proposed Fix
1. Extract and display backend error details
In all three catch blocks, extract the detail from
ApiError:2. Add expandable error detail UI
Replace the plain error
<p>with a collapsible detail:This could be a simple
<details>/<summary>element or a "Show details" toggle.3. Show manual setup when the PATCH fails (Scenario A)
When the
update()PATCH fails, the manual setup section is completely hidden becausewebhooks_enabledremainsfalse. The fix should show manual setup instructions alongside the error even when the toggle PATCH failed:webhooks_enabled— show it whenever there's a webhook-related error4. Auto-reveal manual setup on auto-setup failure (Scenario B)
When the auto-setup catch fires (line 2090-2092), set
webhookStatusto"error"(not"unknown") so that:webhookStatus !== "unknown"istrue)handleRevealSecret()to auto-reveal the URL/secret/instructions5. Show webhook status message for non-success states
The
webhookMessagefromsetupWebhookresponse includes useful info forno_scope,no_token, andmanual_requiredstatuses, but should be visually distinguished for error-like states (e.g. red/amber styling forerror/no_scope/no_token).Affected Code
handleToggleWebhookscatchsettings/page.tsx:2096ApiError.message, no manual setup shownsettings/page.tsx:2090runWebhookSetupcatchsettings/page.tsx:2052ApiError.messagesettings/page.tsx:2150webhooks_enabledis falseshowManualSetuplogicsettings/page.tsx:2124webhooks_enabledto be true — no manual fallback when PATCH failssettings/page.tsx:2276Acceptance Criteria
webhookStatusset to"error"(not"unknown") on auto-setup failure, so retry button and error feedback are visible