Development
rust-errors - Claude MCP Skill
Rust to TypeScript error handling patterns for Tauri apps. Use when defining Rust errors that will be passed to TypeScript, handling Tauri command errors, or creating discriminated union error types.
SEO Guide: Enhance your AI agent with the rust-errors tool. This Model Context Protocol (MCP) server allows Claude Desktop and other LLMs to rust to typescript error handling patterns for tauri apps. use when defining rust errors that will b... Download and configure this skill to unlock new capabilities for your AI workflow.
Documentation
SKILL.md# Rust to TypeScript Error Handling
## Discriminated Union Pattern for Errors
When passing errors from Rust to TypeScript through Tauri commands, use internally-tagged enums to create discriminated unions that TypeScript can handle naturally.
### Rust Error Definition
```rust
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Error, Debug, Serialize, Deserialize)]
#[serde(tag = "name")]
pub enum TranscriptionError {
#[error("Audio read error: {message}")]
AudioReadError { message: String },
#[error("GPU error: {message}")]
GpuError { message: String },
#[error("Model load error: {message}")]
ModelLoadError { message: String },
#[error("Transcription error: {message}")]
TranscriptionError { message: String },
}
```
### Key Rust Patterns
1. **Use internally tagged enums**: `#[serde(tag = "name")]` creates a discriminator field
2. **Follow naming conventions**: Enum variants should be PascalCase
3. **Include structured data**: Each variant can have fields like `message: String`
4. **Single-variant enums are okay**: Use when you want consistent error structure
```rust
// Single-variant enum for consistency
#[derive(Error, Debug, Serialize, Deserialize)]
#[serde(tag = "name")]
enum ArchiveExtractionError {
#[error("Archive extraction failed: {message}")]
ArchiveExtractionError { message: String },
}
```
### TypeScript Error Handling
```typescript
import { type } from 'arktype';
// Define the error type to match Rust serialization
const TranscriptionErrorType = type({
name: "'AudioReadError' | 'GpuError' | 'ModelLoadError' | 'TranscriptionError'",
message: 'string',
});
// Use in error handling
const result = await tryAsync({
try: () => invoke('transcribe_audio_whisper', params),
catch: (unknownError) => {
const result = TranscriptionErrorType(unknownError);
if (result instanceof type.errors) {
// Handle unexpected error shape
return WhisperingErr({
title: 'Unexpected Error',
description: extractErrorMessage(unknownError),
action: { type: 'more-details', error: unknownError },
});
}
const error = result;
// Now we have properly typed discriminated union
switch (error.name) {
case 'ModelLoadError':
return WhisperingErr({
title: 'Model Loading Error',
description: error.message,
action: {
type: 'more-details',
error: new Error(error.message),
},
});
case 'GpuError':
return WhisperingErr({
title: 'GPU Error',
description: error.message,
action: {
type: 'link',
label: 'Configure settings',
href: '/settings/transcription',
},
});
// Handle other cases...
}
},
});
```
### Serialization Format
The Rust enum serializes to this TypeScript-friendly format:
```json
// AudioReadError variant
{ "name": "AudioReadError", "message": "Failed to decode audio file" }
// GpuError variant
{ "name": "GpuError", "message": "GPU acceleration failed" }
```
### Best Practices
1. **Consistent error structure**: All errors have the same shape with `name` and `message`
2. **TypeScript type safety**: Use runtime validation with arktype to ensure type safety
3. **Exhaustive handling**: Switch statements provide compile-time exhaustiveness checking
4. **Don't use `content` attribute**: Avoid `#[serde(tag = "name", content = "data")]` as it creates nested structures
5. **Keep enums private when possible**: Only make public if used across modules
### Anti-Patterns to Avoid
```rust
// DON'T: External tagging (default behavior)
#[derive(Serialize)]
pub enum BadError {
ModelLoadError { message: String }
}
// Produces: { "ModelLoadError": { "message": "..." } }
// DON'T: Adjacent tagging with content
#[derive(Serialize)]
#[serde(tag = "type", content = "data")]
pub enum BadError {
ModelLoadError { message: String }
}
// Produces: { "type": "ModelLoadError", "data": { "message": "..." } }
// DON'T: Manual Serialize implementation when derive works
impl Serialize for MyError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> {
// Unnecessary complexity
}
}
```
This pattern ensures clean, type-safe error handling across the Rust-TypeScript boundary with minimal boilerplate and maximum type safety.Signals
Information
- Repository
- EpicenterHQ/epicenter
- Author
- EpicenterHQ
- Last Sync
- 1/26/2026
- Repo Updated
- 1/26/2026
- Created
- 1/12/2026
Reviews (0)
No reviews yet. Be the first to review this skill!
Related Skills
CLAUDE
CLAUDE.md
Confidence Check
Pre-implementation confidence assessment (≥90% required). Use before starting any implementation to verify readiness with duplicate check, architecture compliance, official docs verification, OSS references, and root cause identification.
coding-standards
Coding Standards & Best Practices
commands
Build, Test & Development Commands
Related Guides
Mastering Python and TypeScript Development with the Claude Skill Guide
Learn how to use the python typescript guide Claude skill. Complete guide with installation instructions and examples.
Mastering VSCode Extension Development with Claude: A Complete Guide to the TypeScript Extension Dev Skill
Learn how to use the vscode extension dev typescript Claude skill. Complete guide with installation instructions and examples.
Next.js SEO Dev: The Essential Claude Skill for Documented React Development
Learn how to use the nextjs seo dev Claude skill. Complete guide with installation instructions and examples.