# Skill: Polish Error Handling

Fix silent error handling patterns across the entire codebase. Every async operation must have visible, actionable error feedback for the user.

## What to Fix

### Frontend (neode-ui/src/)

1. **Silent catch blocks**: Find and replace all `.catch(() => {})` patterns
   - Search: `grep -rn "catch.*=>.*{}" --include="*.vue" --include="*.ts" src/`
   - Replace with: proper error logging + user-visible feedback (toast, inline error, or modal)
   - Pattern:
     ```typescript
     .catch((err) => {
       console.error('[ComponentName] operation failed:', err)
       errorMessage.value = formatError(err)
     })
     ```

2. **Unhandled router.push**: Find `router.push(...).catch(() => {})`
   - Replace with: `router.push(...).catch(console.error)` minimum
   - Or handle NavigationDuplicated gracefully

3. **Silent try/catch**: Find `try { ... } catch { /* empty */ }`
   - Every catch block must either: log the error, show user feedback, or explicitly comment why it's safe to ignore

4. **Missing error states**: For each view, verify:
   - `ref<string | null>` error variable exists
   - Error is displayed in template (inline message, not just console)
   - Error clears on retry or navigation

### Backend (core/)

5. **Silent error swallowing**: Find `unwrap_or_default()` on serialization
   - Replace with proper error propagation or logging
   - Pattern: `.map_err(|e| anyhow::anyhow!("Serialization failed: {}", e))?`

6. **Error response consistency**: All RPC errors should use:
   - Consistent error codes (not random negative numbers)
   - Human-readable messages
   - Consistent JSON structure

## Verification

After fixes, run:
```bash
# Zero silent catches
grep -rn "catch.*=>.*{}\|catch\s*{" neode-ui/src/ --include="*.vue" --include="*.ts" | grep -v node_modules | grep -v "console\|error\|log\|warn"

# Zero empty catch blocks
grep -rn "catch.*{$" neode-ui/src/ --include="*.vue" --include="*.ts" -A1 | grep -P "^\d+-\s*\}"
```

Both should return zero results.

## Error Display Pattern

Use this consistent pattern for user-facing errors:
```typescript
const errorMessage = ref<string | null>(null)

async function doAction() {
  errorMessage.value = null
  try {
    await rpcClient.someCall()
  } catch (err) {
    errorMessage.value = err instanceof Error ? err.message : 'Operation failed'
  }
}
```

Template:
```vue
<p v-if="errorMessage" class="text-red-400 text-sm mt-2">{{ errorMessage }}</p>
```

## Deploy After Fixes

Always deploy and verify on live server after making changes:
```bash
./scripts/deploy-to-target.sh --live
```
