Debugging Workflow (/debug-issue) — express¶
Stack flavor: express. ← Back to overview
[!TIP] Use when the user reports an error, 500 status code, or "something is broken."
Trigger Conditions¶
- Keywords: "Fix", "Debug", "Error", "Broken", "Doesn't work", "500", "404"
- Context: Any specific bug report
0. Early Context Gathering (DO THIS FIRST)¶
[!IMPORTANT] Before diving into code, gather critical context to avoid wasting time in the wrong area.
- [ ] Ask for screenshot if UI-related — identifies the exact component/view
- [ ] Ask "what works vs what doesn't" — if field A works but field B doesn't, this points to field-specific logic
- [ ] Identify the exact view/component name — "Pipeline view" vs "Company Directory" vs "Opportunity modal"
- [ ] Check browser console — ask if there are errors or logs visible
1. Discovery & Reproduction¶
- [ ] Logs: Check backend console logs and browser console/network tab
- [ ] Trace: Locate the exact file and line where the error originates
- [ ] State: Identify the data state (inputs/DB state) that causes the crash
2. Root Cause Analysis¶
- [ ] Validation: Is it a Zod validation error? Check
backend/src/validation/ - [ ] Permissions: Is it an auth issue? Check
authenticatemiddleware andbackend/src/middleware/auth.ts - [ ] Database: Is the Drizzle query correct? Check
backend/src/routes/*.tsandbackend/src/db/schema.ts - [ ] Error routing: Is
next(error)being called? Checkbackend/src/middleware/errorHandler.ts - [ ] Logic: Is it a null/undefined or incorrect business logic?
- [ ] Regression: Did a recent migration or refactor cause this?
3. Proposal & Fix¶
- [ ] Plan: Explain the root cause to the user before fixing
- [ ] Implementation: Apply the fix carefully
- [ ] Cleanup: Remove all
console.logdebug statements added during discovery
4. Verification¶
- [ ] Test: Verify the specific case that was failing
- [ ] Side Effects: Ensure the fix doesn't break related functionality
- [ ] Architecture: Run
/architecture-reviewif the fix involved UI or API changes
Known Issue Patterns¶
Form Dirty State Not Triggering¶
Symptoms: "Save button stays disabled when editing field X, but works for field Y"
Common Causes (check in order):
1. Field-whitelist hooks: hooks/useOpportunityFormDirty.ts only checks fields explicitly listed in opportunityRecordFields. If a field isn't there, it won't trigger dirty state.
2. Shared object references: Initial state and current state point to the same object. Fix with structuredClone().
3. Wrong component/view: User may be on a different screen than assumed.
Quick Debug:
console.log('Initial:', JSON.stringify(initialState?.fieldName));
console.log('Current:', JSON.stringify(currentState?.fieldName));
console.log('isDirty:', isDirty);
API / Backend Errors¶
- Check
backend/src/routes/*.tsfor the endpoint logic - Check
backend/src/db/schema.tsfor column definitions - Verify all catch blocks use
next(error), not manualres.status(500) - Check Supabase RLS policies if getting 403/401
S3 / File Upload Errors¶
- Check
backend/src/services/s3Service.tsfor S3 operation logic - Check
backend/src/routes/documentRoutes.tsfor the upload route - Verify AWS credentials in
.env(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_S3_BUCKET) - Check multer middleware configuration for file size/type limits
UI Component Not Updating¶
- Check if state is being set with a new reference (not mutating existing object)
- Check if
useMemo/useCallbackdependencies are correct - Check if the parent component is re-rendering
Race Conditions / Causal Order Failures¶
Symptoms: "Modals closing too fast", "Intermittent 500 errors", "Deleted items reappearing briefly", "Notifications missing"
Common Causes:
1. Unawaited backend tasks: Side effects (notifications, logs) in routes not awaited before res.json()
2. Eager frontend closure: Modals close on click instead of after await deleteMutation.mutateAsync()
3. Missing mutateAsync: Using mutate (fire-and-forget) instead of mutateAsync
Quick Debug:
- Backend: verify Promise.allSettled() is used for concurrent side effects
- Frontend: verify mutateAsync is awaited before closing modals
- Check for sequence markers in console: [DELETE][1/3], [DELETE][2/3]