Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Error Handling #3301

Open
markbates opened this issue Mar 8, 2024 · 9 comments
Open

Improve Error Handling #3301

markbates opened this issue Mar 8, 2024 · 9 comments
Labels
Enhancement New feature or request

Comments

@markbates
Copy link

Is your feature request related to a problem? Please describe.

Yes. Currently, in both the v2 and v3 versions of the API there is little to no error handling. The result is either panics or calls to log.Fatal. It's wilding frustrating to have a 3rd party library crashing my application.

In idiomatic Go we return an error if there is a problem. In the Wails API however, there are very little errors returned. Instead, when there is a problem the application either crashes with a panic or a call to log.Fatal. This makes applications nearly impossible to test and require the end user to wrap significant portions of the API to prevent these situations.

Describe the solution you'd like

I suggest idiomatic go error handling be implemented and nil checks are implemented.

Consider the following code snippet from the v3 API.

func (a *App) Capabilities() capabilities.Capabilities {
	return a.capabilities
}

If a is nil, then this code will panic and crash my applications and tests.

Consider the same code, but with a nil check and error handling.

func (a *App) Capabilities() ( capabilities.Capabilities, error ) {
	if a == nil {
		return capabilities.Capabilities{}, fmt.Errorf("app is nil")
	}
	return a.capabilities
}

Now, my application, or tests, will no longer panic and crash, but will return an error I can check and handle.

Describe alternatives you've considered

As an alternative to this I've had to wrap the entire v2 API in safe, idiomatic code, https://github.com/markbates/wailsx. This is, obviously, not a long term solution, especially with v3 in alpha. I do hope, however, that it might prove to be a guideline for further API discussion.

Additional context

No response

@markbates markbates added the Enhancement New feature or request label Mar 8, 2024
@leaanthony
Copy link
Member

Hi Mark 👋

Nobody has previously commented on this but it's a valid point. Are you suggesting that we wrap every method with a nil check and return an error? Apart from a nil check, do you have any other examples?

Thanks! 🙏

@markbates
Copy link
Author

Checking for nil is really big start. Prevent crashes is always a big win.

Here's another example from the v2 API where an error would be very useful.

func WindowSetSize(ctx context.Context, width int, height int) {
	appFrontend := getFrontend(ctx)
	appFrontend.WindowSetSize(width, height)
}

I could call this function with illegal values: WindowSetSize(cox, -1, -1). In theory, I shouldn't be able to set the size of the window to negative numbers. Returning an error from this function would catch this issue.

func WindowSetSize(ctx context.Context, width int, height int) error {
	if width < 0 || height < 0 {
		return fmt.Errorf("w or h is less than 0: %d, %d", width, height)
	}

	appFrontend := getFrontend(ctx)
	appFrontend.WindowSetSize(width, height)
	return nil
}

Does that help?

@leaanthony
Copy link
Member

It does, and thanks for bringing the suggestion now as we can absolutely incorporate that into v3.

Just one point of clarity though, what are you using context for?

Cheers 👍

@markbates
Copy link
Author

markbates commented Mar 8, 2024

You tell me. :) Joking asides, that example is in the v2 API. Almost all of those functions take a context as the first argument.

@leaanthony
Copy link
Member

Oh, THAT context. Yeah, that was simply a bad decision 😅 If you discord, it would be great to have you on the server for feedback on v3. If not, then this can work. Thanks again for raising it Mark.

@stffabi
Copy link
Collaborator

stffabi commented Mar 13, 2024

Yeah we absolutely need improvements on the error handling side.

Personally I'm a little surprised about the recommendation for adding all those nil checks of struct instance pointers. As you mention @markbates this is idiomatic Go, so I'm very interested in having some insights why that is seen as idiomatic. Are there any official references about that? IIRC I haven't seen that pattern often, also not that often in Go's own source.

@leaanthony
Copy link
Member

Also, the door is very open to you to come help shape v3 😉

@iamkhalidbashir
Copy link

Also think error handing types is not correct for example for:

func (a *AppApi) GetMachineID() (string, string) {
	id, err := machineid.ID()
	if err != nil {
		return "", err.Error()
	}
	return id, ""
}

the wailjs runtime TS is

export function GetMachineID():Promise<string|string>;

Which is not the same, as TS expects to string either or, it can't diff between result and error message

@BigBallard
Copy link

BigBallard commented Dec 2, 2024

My approach on this is simply interpreting pointer types as possibly being null or undefined somehow as this is the best translation to intention.

For example:

func GetOrder(id string) (Order, *AppError) {
  ...
}

could translate to the TS signature:

export function GetOrder(arg1: String): Promise<Order, AppError|undefined>

Now I could see this becoming messy with multiple return types that could all be pointers, so another approach would be to create a wails generated result type that can have each return type be a field of the result.

Example:

/* 
export interface <FUNC_NAME>Result {
  <TYPE_LC>: <TYPE[|undefined]>
}
*/
export interface GetOrderResult {
  order: Order
  error: Error|undefined
}
export function GetOrder(arg1:String): Promise<GetOrderResult>

This approach would prevent the need panic to force an error on the frontend while making less overhead on the Go side.

Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants