I have a backend with golang that talks to k8s. I want to reformulate the error response that i get from k8s and send it to the frontend.
I want to return a meaningful validation error messages for the user, when he add a non valid name, something already exist ...
And i want something generic not hardcoded in each endpoint's controller.
I am using kubernetes/client-go
.
For example lets say i want to add a hotel to the etcd
, when i try to add the hotel's name: hotel123, that's already exist.
\"hotel123\" already exists
.hotel123 already exists
.For example lets say i want to add a hotel to the etcd
, when i try to add the hotel name: hotel_123, that's alerady exist.
\"hotel_123\" is invalid, Invalid value: \"hotel_123\"...
hotel_123 is invalid
How to return a custom user friendly error message ?
PS: i have multiple functions, so the validation should be generic.
In general (although there are workarounds), if you want to trap an error in order to return a more useful error, you want to ensure the following conditions are met:
In the following example I'm trying to read a config file that doesn't exist. My code checks that the error returned is a fs.PathError
and then throws it's own more useful error. You can extend this general idea to your use case.
package main
import (
"errors"
"fmt"
"io/fs"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
var myError error
config, originalError := clientcmd.BuildConfigFromFlags("", "/some/path/that/doesnt/exist")
if originalError != nil {
var pathError *fs.PathError
switch {
case errors.As(originalError, &pathError):
myError = fmt.Errorf("there is no config file at %s", originalError.(*fs.PathError).Path)
default:
myError = fmt.Errorf("there was an error and it's type was %T", originalError)
}
fmt.Printf("%#v", myError)
} else {
fmt.Println("There was no error")
fmt.Println(config)
}
}
In your debugging, you will find the %T
formatter useful.
For your specific use-case, you can use a Regex to parse out the desired text.
The regex below says:
^\W*
start with any non-alhpanumeric characters(\w+)
capture the alphanumeric string following\W*\s?
match non-alphanumeric characters(is\sinvalid)
capture "is invalid"func MyError(inError error) error {
pattern, _ := regexp.Compile(`^\W*(\w+)\W*\s?(is\sinvalid)(.*)$`)
myErrorString := pattern.ReplaceAll([]byte(inError.Error()), []byte("$1 $2"))
return errors.New(string(myErrorString))
}
As seen on this playground: