Skip to content

API request failures seem to be able to return empty errors #37

@lachlanmunro

Description

@lachlanmunro

Describe the bug

  • UpdateUptimeTest request failures seem to be able to return an empty error ("").
  • GetUptimeTest requests seem to be able to return an empty uptime test object with no error.

Additional context
We are running a small go tool to perform OAuth token updates on StatusCake uptime tests.

To Reproduce
We've since found the Debug option within the library but it's too verbose to run all the time. We've built in flags so we can try to get more detail next time if it becomes reproducible/consistent.

Most recently it was Updating an uptime test. We've seen it a fair few times on the GetUptimeTest too, please note the edge case catches in the code below.

You could use the StatusCake API changes that resulted in support request 22508200886017? They triggered it persistently. My hunch is it's a response that doesn't correspond to the expected response format, but that's a complete guess based on similar issues I've seen elsewhere in client libs.

Expected behavior
Library errors should allow clients to provide context failure to StatusCake. An "" error return is probably never be acceptable.

Detail
I've smashed the relevant bits out of a few places into the below representative code:

client, err := NewStatusCakeClient(statusCakeCfg)
if err != nil {
	return "", err
}

testResp, err := client.GetUptimeTest(ctx, id).Execute()
if err != nil {
	return "", fmt.Errorf("failed to get Uptime Test: %w", err)
}

if testResp.Data.Name == "" {
	return "", fmt.Errorf("failed to get Uptime Test: %w", errors.New("response returned without error but has no name"))
}

if testResp.Data.ID == "" {
	return "", fmt.Errorf("failed to get Uptime Test: %w", errors.New("response returned without error but has no ID"))
}

test := testResp.Data
l.Info().Str("name", t.Name).Msgf("Found test: %s", t.Name)
token, err := GetOAuthTokens(ctx, l, oathConfig, refreshToken)
if err != nil {
	return "", fmt.Errorf("failed to get new token: %w", err)
}

if token.AccessToken == "" {
	return token.RefreshToken, errors.New("access token was empty")
}

l.Debug().Str("token", token.AccessToken).Str("refreshtoken", token.RefreshToken).Msgf("Got new token: %s", token.AccessToken)
bytes, err := json.Marshal(&struct {
	Content       string `json:"content-type"`
	Cache         string `json:"cache-control"`
	Authorization string `json:"authorization"`
}{
	Content:       "application/json",
	Cache:         "no-cache",
	Authorization: fmt.Sprintf("Bearer %s", token.AccessToken),
})

header := string(bytes)
l.Debug().Msgf("Got new header state: %s", header)
if err != nil {
	return token.RefreshToken, fmt.Errorf("failed to encode new custom header state: %w", err)
}

r := client.UpdateUptimeTest(ctx, id).CustomHeader(customHeader)
if err := r.Execute(); err != nil {
	return token.RefreshToken, fmt.Errorf("failed to update uptime test: %w", err)
}

return token.RefreshToken, nil

Application logs look like the following, note the lack of error detail, I'd expect an error there that described the issue.

2024-04-17T11:31:29.750+01:00 INF Found test: Product - Prod - API every=600000 id=123456 name="Product - Prod - API"
2024-04-17T11:31:29.891+01:00 ERR Failed to update Uptime Test authentication: failed to update uptime test:  error="failed to update uptime test: " every=600000 id=123456 

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions