Compare commits

1 Commits

Author SHA1 Message Date
decentral1se 412c2f48ea feat: better error handling 2026-07-23 17:57:42 +02:00
6 changed files with 157 additions and 0 deletions
+1
View File
@@ -3,6 +3,7 @@ examples/connect-desktop/build
examples/connect-desktop/frontend/dist
examples/connect-desktop/frontend/wailsjs
examples/connect/connect
examples/errors/errors
examples/pairchat/pairchat
examples/timeserve/timeserve
iroh-go/target/
+107
View File
@@ -0,0 +1,107 @@
package iroh_ffi
import (
"errors"
"fmt"
)
// As casts an error to IrohError and back, extracting relevant error message
// information. It is a single argument variant of the typical errors.As API
// because we always expect an IrohError back from the iroh FFI bindings. The
// bindings do not return an IrohError for reasons and will not for the
// forseeable future due to API stability guarantees.
func As(err error) error {
if err, ok := errors.AsType[IrohError](err); ok {
return errors.New(fmt.Sprintf("%s: %s", err.Message(), err.DebugMessage()))
}
return err
}
// Is suports matching against the stable iroh error taxonomy using the error
// sentinel construction below. The caller must pass in a valid error sentinel
// specified by this library, e.g. iroh.BindError.
func (e *IrohError) Is(target error) bool {
if err, ok := errors.AsType[sentinel](target); ok {
return uint(e.Kind()) == err.kind
}
return false
}
type sentinel struct {
kind uint
message string
}
func (s sentinel) Error() string {
return s.message
}
var InvalidInputError error = sentinel{
kind: uint(IrohErrorKindInvalidInput),
message: "iroh: invalid input supplied by the caller",
}
var BindError error = sentinel{
kind: uint(IrohErrorKindBind),
message: "iroh: failure while initiating or completing an outgoing connection",
}
var ConnectError error = sentinel{
kind: uint(IrohErrorKindConnect),
message: "iroh: failure while initiating or completing an outgoing connectio",
}
var ConnectionError error = sentinel{
kind: uint(IrohErrorKindConnection),
message: "iroh: an established connection failed or closed unexpectedly",
}
var AlpnError error = sentinel{
kind: uint(IrohErrorKindAlpn),
message: "iroh: ALPN negotiation or lookup failed",
}
var KeyParsingError error = sentinel{
kind: uint(IrohErrorKindKeyParsing),
message: "iroh: endpoint id / public key parsing failed",
}
var TicketParsingError error = sentinel{
kind: uint(IrohErrorKindKeyParsing),
message: "iroh: ticket parsing failed",
}
var RelayError error = sentinel{
kind: uint(IrohErrorKindRelay),
message: "iroh: stream read/write/control operation failed",
}
var StreamError error = sentinel{
kind: uint(IrohErrorKindStream),
message: "iroh: datagram send/receive operation failed",
}
var DatagramError error = sentinel{
kind: uint(IrohErrorKindDatagram),
message: "iroh: datagram send/receive operation failed",
}
var FCallbackError error = sentinel{
kind: uint(IrohErrorKindCallback),
message: "iroh: foreign callback failed",
}
var ClosedError error = sentinel{
kind: uint(IrohErrorKindClosed),
message: "iroh: operation was attempted on a closed stream/connection/resource",
}
var TimeoutError error = sentinel{
kind: uint(IrohErrorKindTimeout),
message: "iroh: operation timed out",
}
var InternalError error = sentinel{
kind: uint(IrohErrorKindInternal),
message: "iroh: unclassified internal error",
}
+5
View File
@@ -0,0 +1,5 @@
# errors
How to deal with error handling in a convenient way. See
[`#263`](https://github.com/n0-computer/iroh-ffi/issues/263) for the juicy
details.
+37
View File
@@ -0,0 +1,37 @@
package main
import (
"errors"
iroh "git.coopcloud.tech/decentral1se/iroh-go"
)
func main() {
preset := iroh.PresetN0DisableRelay()
opts := iroh.EndpointOptions{
Preset: &preset,
Alpns: &[][]byte{[]byte("iroh-go-errors/0")},
}
endpoint, err := iroh.EndpointBind(opts)
// BEGIN API PREVIEW ZONE
// 1. convert error to IrohError with As
// bring IrohError.Message/DebugMessage back
// maintain `err != nil` compatibility
if err := iroh.As(err); err != nil {
panic(err)
}
// 1. no As machinery required
// sentinel check with errors.Is support
// works like usual `err`
if err != nil && errors.Is(err, iroh.BindError) {
panic(err)
}
// END API PREVIEW ZONE
endpoint.Online()
}
+7
View File
@@ -0,0 +1,7 @@
module git.coopcloud.tech/decentral1se/iroh-go/examples/errors
go 1.26.1
require git.coopcloud.tech/decentral1se/iroh-go v0.0.0-20260717110820-68ad06fe2a25
replace git.coopcloud.tech/decentral1se/iroh-go => ../../
View File