always_fails.mdin: /docs/internal/components/

components.AlwaysFails - captures itself

Error, captured by AlwaysFails:

View(components.AlwaysFails): this view will always fail

components.AlwaysFails !!FAILED!! - captured by component

Error Captured by component:

tpl 'component': slot 'body': View(components.AlwaysFails): this view will always fail

The components you see above are rendered by the init register hook and are declared below. This demonstrates how you can do error handling with veun.

To do this, we create a view that always fails. It's configured to either capture its own error, or not. But it always fails.

When it doesn't capture its own error, the rendering parent component captures it. If we left it alone, we'd end up with a 500 server error.

import (


init component registration

What renders the components at the top of this page :)

func init() {
    show(AlwaysFails{OwnErrorCapture: true}, AlwaysFails{OwnErrorCapture: false})

the view

type AlwaysFails struct {
	OwnErrorCapture bool

AlwaysFails has two implementations based on OwnErrorCapture.

func (v AlwaysFails) View(_ context.Context) (*veun.View, error) {

Either we propagate an error out of the view directly:

if !v.OwnErrorCapture {
    return nil, errors.New("this view will always fail")

Or we create uh kind of recursively create view that captures the error of itself.

// N.B. Why yes, this is a recursive definition.
return veun.V(AlwaysFails{}).WithErrorHandler(v), nil

Closing View:


Error Handler

As we see above, this view is also an error handler.

var _ veun.ErrorHandler = AlwaysFails{}

func (v AlwaysFails) ViewForError(_ context.Context, err error) (veun.AsView, error) {
    return errorBody("Error, captured by AlwaysFails:", err.Error()), nil


We fulfill the Component interface by giving this a description in the component UI.

func (v AlwaysFails) Description() string {
	if v.OwnErrorCapture {
		return "captures itself"

	return "captured by component"