Handling Errors

      +
      Errors are inevitable. The developer’s job is to be prepared for whatever is likely to come up — and to try and be prepared for anything that conceivably could come up.

      The Go SDK works nicely with the errors package to interrogate errors. Of course, you can also just log them and fail the operation.

      Using errors.As

      All errors from the Go SDK that occur from an interaction with the server have ColumnarError in the error chain. This error indicates a client-server interaction failed. Specifically, it indicates a request could not be dispatched, a response was not received, or the response indicated an error.

      	result, err := cluster.ExecuteQuery(
      		ctx,
      		"select 1=1",
      	)
      	if err != nil {
      		var columnarErr cbcolumnar.ColumnarError
      		if errors.As(err, &columnarErr) {
      			// Do something with this error.
      		}
      
      		// This error occurred out of a client-server interaction.
      	}

      The SDK also exposes a QueryError type, which wraps ColumnarError and exposes more information about the query context. Specifically, this error allows access to the error code and message returned directly from the query engine. This error only occurs when the query engine is attempting to execute a query.

      	handleQueryError := func(err error) {
      		if err != nil {
      			var queryErr cbcolumnar.QueryError
      			if errors.As(err, &queryErr) {
      				fmt.Printf("Error code: %d, error message: %s", queryErr.Code(), queryErr.Message())
      				return
      			}
      
      			// This error isn't a result of query processing, possibly something like a connection error.
      		}
      	}
      
      	result, err := cluster.ExecuteQuery(
      		ctx,
      		"selec 1=1", // Syntax error
      	)
      	handleQueryError(err)

      Using errors.Is

      Errors in the Go SDK primarily fall into a small number of categories:

      • ErrColumnar — Occurs when a client-server interaction fails. This will be the base error if no more specific error is detected.

      • ErrQuery — Occurs when a server error is encountered while executing a query, excluding errors that fall into ErrInvalidCredential or ErrTimeout.

      • ErrInvalidCredential — Occurs when the credentials provided to the server are invalid. This can be returned by ExecuteQuery if SDK bootstrapping fails or be returned from the query engine.

      • ErrTimeout — Occurs when a query times out on the server.

      • Other - this includes platform errors and SDK errors like ErrInvalidArgument

      Timeouts

      Timeouts are a common source of errors in distributed systems. The Go SDK exposes timeouts in two ways, depending on the context.Context provided to the operation.

      If the context.Context provided to ExecuteQuery contains a Deadline then the timeout is controlled by the context. If a timeout occurs in this case, then it will be returned as a context.DeadlineExceeded error. Note: the context.CancelFunc is also respected, if the Context is canceled then a context.Canceled error will be returned.

      If there is no Deadline specified on the Context then the SDK will apply the timeout specified by the QueryTimeout from ClusterOptions. If a timeout occurs in this case, then it will be returned as an ErrTimeout error.

      Errors that prevent dispatch

      Sometimes errors occur during SDK bootstrap which prevents the SDK from discovering the cluster topology. These errors prevent the SDK from knowing where to send a query. When a bootstrap error is detected, then the SDK will fast-fail the operation and return the error.

      Note: this only applies before the SDK has discovered the cluster topology. Once the topology is known, then the SDK will not fast-fail operations due to any underlying connection errors.