Skip to content
Errors and pagination

Errors and pagination

Errors

Options are validated before any request is sent: a missing or invalid parameter is returned as a *ValidationError, naming the field. When SonarQube answers with an error status, the error is a *ResponseError, carrying the status code, the message and the raw body.

client, err := sonar.NewClientFromEnv()
if err != nil {
	panic(err)
}

_, _, err = client.Qualitygates.ProjectStatus(context.Background(), &sonar.QualitygatesProjectStatusOptions{})

var validationErr *sonar.ValidationError
if errors.As(err, &validationErr) {
	fmt.Println("invalid field:", validationErr.Field)
}

var responseErr *sonar.ResponseError
if errors.As(err, &responseErr) {
	fmt.Println("SonarQube answered", responseErr.StatusCode)
}

Example on pkg.go.dev

To branch on a status code without unwrapping the error, use the helpers IsNotFound, IsUnauthorized, IsForbidden, IsConflict, IsRateLimited and IsServerError:

client, err := sonar.NewClient(nil,
	sonar.WithBaseURL("https://sonarqube.example.com/api/"),
	sonar.WithToken("my-token"),
)
if err != nil {
	panic(err)
}

_, err = client.Projects.Delete(context.Background(), &sonar.ProjectsDeleteOptions{Project: "missing-project"})
if sonar.IsNotFound(err) {
	fmt.Println("project not found")
}

Example on pkg.go.dev

Pagination

Paginated V1 endpoints take PaginationArgs (Page, starting at 1, and PageSize, up to 500) and return a Paging with the page index, the page size and the total:

client, err := sonar.NewClientFromEnv()
if err != nil {
	panic(err)
}

issues, _, err := client.Issues.Search(context.Background(), &sonar.IssuesSearchOptions{
	PaginationArgs: sonar.PaginationArgs{Page: 1, PageSize: 100},
	Projects:       []string{"my-project"},
	IssueStatuses:  []string{"OPEN", "CONFIRMED"},
})
if err != nil {
	panic(err)
}

fmt.Printf("page %d: %d of %d issues\n", issues.Paging.PageIndex, len(issues.Issues), issues.Paging.Total)

for _, issue := range issues.Issues {
	fmt.Println(issue.Key, issue.Message)
}

Example on pkg.go.dev

Most of them also have an ...All variant (SearchAll, ListAll) that walks through every page and returns the merged results:

client, err := sonar.NewClientFromEnv()
if err != nil {
	panic(err)
}

users, _, err := client.Users.SearchAll(context.Background(), &sonar.UsersSearchOptions{
	Query: "john",
})
if err != nil {
	panic(err)
}

for _, user := range users {
	fmt.Println(user.Login)
}

Example on pkg.go.dev

SonarQube refuses to page past 10,000 results on some endpoints, such as the issues search. Narrow the search with filters rather than fetching everything on large instances.

In the CLI, the same behavior is available with --all (see CLI pagination).