Always make fatal errors json-serializable (#14396)
This commit is contained in:
parent
a8f95ef6d0
commit
4d6109d3ab
3 changed files with 39 additions and 16 deletions
21
cmd/error.go
21
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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue