Przejdź do treści
Biblioteka skilli
Programowanie · Integracja z narzędziem

rust-errors

/rust-errors

Projektuje obsługę błędów między Rustem a TypeScriptem w aplikacjach Tauri, w tym typy błędów dla wywołań komend invoke.

Repozytorium
epicenter ↗
Licencja
MIT
Ostatnia zmiana repozytorium
13.11.2026

Ocena i bezpieczeństwo

95/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść30 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
1
Przestarzałość

Brak sygnałów. Repozytorium zmienione 13.11.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Projektuje obsługę błędów między Rustem a TypeScriptem w aplikacjach Tauri, w tym typy błędów dla wywołań komend invoke.

Oryginalny opis (EN)

Rust to TypeScript error handling for Tauri apps. Use when mentioning Rust errors, Tauri command errors, invoke errors, or defining Rust error types for TS consumption.

Jak działa

  1. Reference Repositories
  2. Upstream Grounding
  3. Let Rust define the failure
  4. Generate the application result shape
  5. Keep the generated contract in sync
  6. tracing ↔ wellcrafted/logger
Sekcje z nagłówków SKILL.md, w oryginale · 100 linii, 961 słów
Podgląd SKILL.md
---
name: rust-errors
description: Rust to TypeScript error handling for Tauri apps. Use when mentioning Rust errors, Tauri command errors, invoke errors, or defining Rust error types for TS consumption.
metadata:
  author: epicenter
  version: '1.0'
---

# Rust to TypeScript Error Handling
## Reference Repositories

- [Tauri](https://github.com/tauri-apps/tauri): Desktop app framework (source of Rust-to-TypeScript error patterns)

## Upstream Grounding

When Rust error serialization, Tauri command error transport, IPC payload shape, generated bindings, or frontend invoke error behavior affects correctness, use source-backed grounding before relying on memory. If DeepWiki MCP is available, ask a narrow question against `tauri-apps/tauri`; if it is unavailable or the repo is not indexed, use upstream source or official docs directly. Treat DeepWiki as orientation, then verify decisive details against local Rust code, generated bindings, installed crates, TypeScript types, source, or official docs before changing code.

Skip DeepWiki for local error naming conventions already documented below.

Use this skill when a Rust command returns failures that TypeScript consumes. The `tauri` skill owns command registration, generated bindings, capabilities, and native verification. The `error-handling` skill owns Result composition and presentation after the IPC boundary. The `logging` skill owns diagnostic levels and sinks.

## Let Rust define the failure

A command returns `Result<T, E>` when failure is part of its contract. Define an error variant when a caller can respond differently or needs structured data; keep operational detail in `message`. The recorder's `PermissionDenied`, `NoInputDevice`, and `Busy` variants are examples. Do not divide one frontend action into several variants merely to label different internal causes. An internal Rust error that never crosses IPC does not need Serde or Specta derives.

For a typed command error that crosses IPC, derive `serde::Serialize` and `specta::Type` from the same enum. Derive `Deserialize` only when the value also crosses back into Rust. An internally tagged enum such as `#[serde(tag = "name")]` gives TypeScript a discriminant for exhaustive handling:

```rust
#[derive(Debug, thiserror::Error, serde::Serialize, specta::Type)]
#[serde(tag = "name")]
pub enum RecordingError {
    #[error("{message}")]
    PermissionDenied { message: String },
    #[error("{message}")]
    Failed { message: String },
}
```

Keep the error non-nullable. Specta's `DataError` mode uses `null` to mean success and rejects nullable command error types during binding export. A success value may itself be nullable. Do not add a parallel ArkType schema or handwritten TypeScript union for a generated Rust error. Browser code can use explicit `import type` from the generated bindings without loading the Tauri runtime.

## Generate the application result shape

The native plugins' Specta builders set `ErrorHandlingMode::DataError`. The generated command returns `{ data: T, error: null } | { data: null, error: E }`, which is compatible with Wellcrafted's `Result<T, E>`. Callers branch on `error !== null`, forward an error they do not own, and let the interaction owner present the final outcome. Infallible commands retain their plain generated return type.

This mode changes the generated TypeScript API. Tauri still sends a Rust `Err` through its rejected IPC channel. The generated helper catches a non-`Error` rejection and casts it to `E`; it rethrows a JavaScript `Error`. Generation therefore establishes the compile-time contract, not runtime validation of every rejection. Do not present an unexpected thrown failure as a known Rust domain variant. Adapt a transport rejection only where an operation deliberately owns that failure meaning.

A consumer's command boundary combines generated commands with any handwritten raw-byte command. It must not reshape every generated command: `DataError` already produces the application Result. A raw `tauri::ipc::Response` command remains handwritten because Specta cannot export that response type.

## Keep the generated contract in sync

Regenerate the bindings owned by a changed plugin and review their diff. Generated types should change when the wire contract changes. Check the relevant TypeScript type assertions and consumers. Keep exhaustive `switch (error.name)` handling where a caller translates every variant.

Rust's `tracing` and TypeScript's `wellcrafted/logger` both choose severity at the emission site, not on the error variant. See `logging` for the diagnostic contract and the mapping below. A returned `Err` is not itself a log event; log where an owner can add context or where the failure would otherwise be invisible.

## `tracing` ↔ `wellcrafted/logger`

`defineErrors` mirrors `thiserror`; the workspace logger mirrors `tracing`. Together they give TypeScript the same split Rust has: errors are data, level is chosen at the emit site.

### Level mapping (5 levels, no `fatal`)

| `tracing` macro | Workspace `Logger` method | Use when |
|---|---|---|
| `tracing::trace!(...)` | `log.trace(message, data?)` | Per-token / per-message noise for deep debugging |
| `tracing::debug!(...)` | `log.debug(message, data?)` | Internal state transitions (handshakes, cache fills) |
| `tracing::info!(...)` | `log.info(message, data?)` | Lifecycle events (connected, loaded, flushed) |
| `tracing::warn!(?err)` | `log.warn(err)` | Recoverable failure: retry path, fallback taken |
| `tracing::error!(?err)` | `log.error(err)` | Unrecoverable at this layer: call it loudly |

`tracing` has no `fatal`; neither do we. Process termination is the app's decision (`process.exit`), not the library's.

### Level on the variant? No.

```rust
// Rust: level is on the CALL, not the enum variant
tracing::warn!(?err, "cache miss"); // same err, different sites
tracing::error!(?err, "giving up");
```

```ts
// TS: same rule
log.warn(CacheError.Miss({ key }));  // recoverable
log.error(CacheError.Miss({ key })); // terminal
```

No Rust logging crate attaches level to the error type (`thiserror`, `anyhow`, `slog`, `log`). `miette` is the exception, but it is a compiler-diagnostics library, not a general logger. We follow `tracing`: level is context, not identity.

### The `?err` idiom ↔ `tapErr`

`tracing`'s `?err` interpolates a structured error field into the log event. In TS, the Result-flow equivalent is `tapErr` (from `wellcrafted/result`):

```rust
let result = do_thing().inspect_err(|err| tracing::warn!(?err, "do_thing failed"));
```

```ts
import { tapErr } from 'wellcrafted/result';

const result = await tryAsync({
  try: () => doThing(),
  catch: (cause) => DoThingError.Failed({ cause }),
}).then(tapErr(log.warn));
```

Both: pass-through on success, log the structured error on failure.

In practice this shape is rare in epicenter. Most call sites need the Ok data locally and so branch on `result.error` and log inside the branch. Reach for `tapErr` only when the Result flows out of the function in a `.then(...)` chain.

Wersje

RepozytoriumWynikLicencja
Ta strona · EpicenterHQ/epicenter95MIT
zjunlp/skills100MIT
rewrite-rs/skills95BSD-3-Clause

Migawka bazy z 13.11.2026 · wersja paczki 0d4fbfb98a3a (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 95rust-error-handling
    Opisuje obsługę błędów w Rust z Result, Option, własnymi typami błędów, thiserror i anyhow.
  • 100tauri
    Prowadzi przez tworzenie aplikacji Tauri v2: scaffolding create-tauri-app, komendy Rust wywoływane przez invoke, zdarzenia, pluginy, błędy uprawnień w capabilities, instalatory i podpisywanie.
  • 100screenpipe-tauri
    Dodaje i zmienia komendy Tauri oraz bindingi TypeScript w aplikacji desktopowej screenpipe, w tym typy Rust eksportowane do frontendu.
  • 100handling-rust-errors
    Opisuje wzorce obsługi błędów HASH z użyciem crate error-stack w Rust: typy Result i Report, własne błędy, change_context, attach, trait Error i dokumentowanie warunków błędów.
  • 100tauri
    Pomaga w Tauri: komendy, uprawnienia, capabilities, konfiguracja bezpieczeństwa, ścieżki, operacje na plikach między platformami i natywne API systemu plików.
  • 100handling-rust-errors
    Opisuje wzorce obsługi błędów HASH z crate error-stack: typy Result i Report, własne błędy, change_context, attach i implementację Error trait.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.