diff --git a/cmd/error.go b/cmd/error.go index d2e175744..7744080c8 100644 --- a/cmd/error.go +++ b/cmd/error.go @@ -28,6 +28,27 @@ const ( ClassSponsorship ) +// FatalError is an error that can be marshaled +type FatalError struct { + err error +} + +func (e *FatalError) Error() string { + return e.err.Error() +} + +func (e FatalError) MarshalJSON() ([]byte, error) { + if je, ok := e.err.(json.Marshaler); ok { + return je.MarshalJSON() + } + + return json.Marshal(struct { + Error string `json:"error"` + }{ + Error: e.err.Error(), + }) +} + // DeviceError indicates the specific device that failed type DeviceError struct { Name string diff --git a/cmd/helper.go b/cmd/helper.go index a42a46c34..183f0051f 100644 --- a/cmd/helper.go +++ b/cmd/helper.go @@ -75,23 +75,25 @@ func shutdownDoneC() <-chan struct{} { return doneC } -func wrapError(err error) error { - if err != nil { - var opErr *net.OpError - var pathErr *os.PathError +func wrapFatalError(err error) error { + if err == nil { + return nil + } - switch { - case errors.As(err, &opErr): - if opErr.Op == "listen" && strings.Contains(opErr.Error(), "address already in use") { - err = fmt.Errorf("could not open port- check that evcc is not already running (%w)", err) - } + var opErr *net.OpError + var pathErr *os.PathError - case errors.As(err, &pathErr): - if pathErr.Op == "remove" && strings.Contains(pathErr.Error(), "operation not permitted") { - err = fmt.Errorf("could not remove file- check that evcc is not already running (%w)", err) - } + switch { + case errors.As(err, &opErr): + if opErr.Op == "listen" && strings.Contains(opErr.Error(), "address already in use") { + err = fmt.Errorf("could not open port- check that evcc is not already running (%w)", err) + } + + case errors.As(err, &pathErr): + if pathErr.Op == "remove" && strings.Contains(pathErr.Error(), "operation not permitted") { + err = fmt.Errorf("could not remove file- check that evcc is not already running (%w)", err) } } - return err + return &FatalError{err} } diff --git a/cmd/root.go b/cmd/root.go index a7c17e839..ecdd9aa19 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -291,7 +291,7 @@ func runRoot(cmd *cobra.Command, args []string) { if err != nil { // improve error message - err = wrapError(err) + err = wrapFatalError(err) valueChan <- util.Param{Key: keys.Fatal, Val: err} // TODO stop reboot loop if user updates config (or show countdown in UI) @@ -307,5 +307,5 @@ func runRoot(cmd *cobra.Command, args []string) { // uds health check listener go server.HealthListener(site) - log.FATAL.Println(wrapError(httpd.ListenAndServe())) + log.FATAL.Println(wrapFatalError(httpd.ListenAndServe())) }