Agent skill
midnight-dapp:error-handling
Use when implementing error handling in Midnight DApps, displaying errors to users, handling proof generation failures, managing transaction rejections, or dealing with network disconnections.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/error-handling-aaronbassett-midnight-knowledgeba
SKILL.md
Error Handling
Handle errors gracefully in Midnight DApps with user-friendly messaging, proper error classification, and recovery strategies.
When to Use
- Displaying errors to users in a helpful way
- Implementing error boundaries for React components
- Handling proof generation failures
- Managing transaction rejections and contract errors
- Dealing with network disconnections (indexer, proof server)
- Creating consistent error messaging across your DApp
Key Concepts
Error Taxonomy
Midnight DApps encounter several categories of errors:
| Category | Source | Examples |
|---|---|---|
| Proof Errors | ZK proof generation | Timeout, constraint violations, witness failures |
| Transaction Errors | Contract execution | Insufficient balance, state conflicts, rejections |
| Network Errors | Infrastructure | Indexer down, proof server unavailable, WebSocket disconnect |
| Wallet Errors | User interaction | Not installed, rejected, wrong network |
User-Friendly Messaging
Technical errors should be translated to actionable messages:
// Technical error
"Circuit constraint failed at gate 1042: input > max_value"
// User-friendly message
"The amount exceeds the maximum allowed. Please enter a smaller value."
Recovery Patterns
Different errors require different recovery strategies:
- Retryable: Timeouts, temporary network issues - offer retry button
- User Action Required: Wrong network, insufficient balance - guide user
- Fatal: Contract bugs, invalid state - show support contact
References
| Document | Description |
|---|---|
| proof-errors.md | ZK proof failures and diagnosis |
| transaction-errors.md | Contract execution errors |
| network-errors.md | Connection and timeout handling |
| user-messaging.md | UX guidelines for error display |
Examples
| Example | Description |
|---|---|
| error-boundary/ | React error boundary for Midnight |
| error-toast/ | Toast notification component |
| typed-errors/ | Custom error classes and catalog |
Quick Start
1. Create Typed Errors
import { MidnightError, ErrorCode } from './MidnightErrors';
// Throw typed errors in your code
throw new MidnightError(
ErrorCode.PROOF_TIMEOUT,
'Proof generation timed out',
{ timeoutMs: 60000, operation: 'transfer' }
);
2. Classify Unknown Errors
import { classifyError } from './errorUtils';
try {
await contract.callTx.transfer(recipient, amount, witnesses);
} catch (error) {
const classified = classifyError(error);
// { code, message, userMessage, suggestion, retryable, category }
}
3. Display to Users
import { useErrorToast } from './useErrorToast';
function TransferButton() {
const { showError } = useErrorToast();
const handleTransfer = async () => {
try {
await performTransfer();
} catch (error) {
showError(error); // Shows user-friendly toast
}
};
}
4. Wrap Components
import { MidnightErrorBoundary } from './MidnightErrorBoundary';
function App() {
return (
<MidnightErrorBoundary
onReset={() => window.location.reload()}
fallback={<ErrorPage />}
>
<MyDApp />
</MidnightErrorBoundary>
);
}
Common Patterns
Error Classification Utility
interface ClassifiedError {
code: string;
message: string;
userMessage: string;
suggestion: string;
retryable: boolean;
category: 'proof' | 'transaction' | 'network' | 'wallet' | 'unknown';
}
function classifyError(error: unknown): ClassifiedError {
if (error instanceof MidnightError) {
return {
code: error.code,
message: error.message,
userMessage: ERROR_CATALOG[error.code].userMessage,
suggestion: ERROR_CATALOG[error.code].suggestion,
retryable: ERROR_CATALOG[error.code].retryable,
category: ERROR_CATALOG[error.code].category,
};
}
// Classify by error message patterns
const message = error instanceof Error ? error.message : String(error);
return classifyByMessage(message);
}
Retry with Backoff
async function withRetry<T>(
operation: () => Promise<T>,
options: {
maxRetries: number;
baseDelayMs: number;
shouldRetry: (error: unknown) => boolean;
}
): Promise<T> {
let lastError: unknown;
for (let attempt = 1; attempt <= options.maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
if (!options.shouldRetry(error) || attempt === options.maxRetries) {
throw error;
}
const delay = options.baseDelayMs * Math.pow(2, attempt - 1);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
Error Context Provider
const ErrorContext = createContext<ErrorContextValue | null>(null);
function ErrorProvider({ children }: { children: ReactNode }) {
const [errors, setErrors] = useState<ClassifiedError[]>([]);
const addError = useCallback((error: unknown) => {
const classified = classifyError(error);
setErrors(prev => [...prev, classified]);
// Auto-dismiss non-critical errors
if (classified.category !== 'wallet') {
setTimeout(() => dismissError(classified.code), 5000);
}
}, []);
const dismissError = useCallback((code: string) => {
setErrors(prev => prev.filter(e => e.code !== code));
}, []);
return (
<ErrorContext.Provider value={{ errors, addError, dismissError }}>
{children}
</ErrorContext.Provider>
);
}
Error Handling Best Practices
- Never swallow errors silently - Always log or display
- Provide actionable messages - Tell users what they can do
- Log technical details - Keep full error info for debugging
- Use error boundaries - Prevent cascading failures in UI
- Categorize appropriately - Different errors need different handling
- Test error paths - Verify error UI works correctly
- Consider accessibility - Error messages should work with screen readers
Related Skills
wallet-integration- Wallet-specific error handlingproof-handling- Proof generation error patternstransaction-flows- Transaction error recoverystate-management- State read error handling
Related Commands
/dapp-check- Validates error handling patterns/dapp-debug errors- Diagnose error handling issues
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?