tessl install tessl/golang-github-com-azure-azure-sdk-for-go-sdk-storage-azqueue-v2@2.0.1Azure Queue Storage SDK for Go provides comprehensive client library for interacting with Azure's cloud-based message queue service including queue management, message operations, and multiple authentication methods.
The queueerror package (github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/v2/queueerror) provides comprehensive error handling capabilities including predefined error codes and helper functions for identifying and handling specific Azure Queue Storage errors.
Check if an error matches specific error codes.
// Check if error matches any of the specified error codes
func HasCode(err error, codes ...Code) boolUsage:
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/v2"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/v2/queueerror"
)
// Attempt to delete queue
_, err := serviceClient.DeleteQueue(context.TODO(), "myqueue", nil)
if queueerror.HasCode(err, queueerror.QueueBeingDeleted, queueerror.QueueNotFound) {
// Queue is being deleted or already doesn't exist - safe to ignore
fmt.Println("Queue already deleted or being deleted")
} else if err != nil {
// Handle other errors
return fmt.Errorf("failed to delete queue: %w", err)
}// Error code returned by Azure Queue Storage service
type Code = generated.StorageErrorCodeAll Azure Queue Storage service errors are returned as *azcore.ResponseError with an ErrorCode field containing one of the predefined error codes.
var (
// Error returned when attempting to create SAS URL without SharedKeyCredential
MissingSharedKeyCredential = errors.New("SAS can only be signed with a SharedKeyCredential")
)Usage:
import "errors"
sasURL, err := queueClient.GetSASURL(permissions, expiry, nil)
if errors.Is(err, queueerror.MissingSharedKeyCredential) {
// Client was not created with SharedKeyCredential
fmt.Println("Cannot generate SAS - SharedKeyCredential required")
}const (
AccountAlreadyExists Code = "AccountAlreadyExists"
AccountBeingCreated Code = "AccountBeingCreated"
AccountIsDisabled Code = "AccountIsDisabled"
)Usage:
if queueerror.HasCode(err, queueerror.AccountIsDisabled) {
fmt.Println("Storage account is disabled")
}const (
AuthenticationFailed Code = "AuthenticationFailed"
AuthorizationFailure Code = "AuthorizationFailure"
AuthorizationPermissionMismatch Code = "AuthorizationPermissionMismatch"
AuthorizationProtocolMismatch Code = "AuthorizationProtocolMismatch"
AuthorizationResourceTypeMismatch Code = "AuthorizationResourceTypeMismatch"
AuthorizationServiceMismatch Code = "AuthorizationServiceMismatch"
AuthorizationSourceIPMismatch Code = "AuthorizationSourceIPMismatch"
InsufficientAccountPermissions Code = "InsufficientAccountPermissions"
InvalidAuthenticationInfo Code = "InvalidAuthenticationInfo"
)Usage:
if queueerror.HasCode(err,
queueerror.AuthenticationFailed,
queueerror.InvalidAuthenticationInfo) {
fmt.Println("Authentication failed - check credentials")
}
if queueerror.HasCode(err,
queueerror.AuthorizationPermissionMismatch,
queueerror.InsufficientAccountPermissions) {
fmt.Println("Insufficient permissions for operation")
}
if queueerror.HasCode(err, queueerror.AuthorizationSourceIPMismatch) {
fmt.Println("Request from unauthorized IP address")
}const (
QueueAlreadyExists Code = "QueueAlreadyExists"
QueueBeingDeleted Code = "QueueBeingDeleted"
QueueDisabled Code = "QueueDisabled"
QueueNotEmpty Code = "QueueNotEmpty"
QueueNotFound Code = "QueueNotFound"
)Usage:
// Handle queue creation
_, err := queueClient.Create(context.TODO(), nil)
if queueerror.HasCode(err, queueerror.QueueAlreadyExists) {
fmt.Println("Queue already exists - continuing")
} else if err != nil {
return err
}
// Handle queue deletion
_, err = queueClient.Delete(context.TODO(), nil)
if queueerror.HasCode(err, queueerror.QueueNotFound) {
fmt.Println("Queue not found - already deleted")
} else if queueerror.HasCode(err, queueerror.QueueBeingDeleted) {
fmt.Println("Queue is being deleted")
} else if err != nil {
return err
}const (
MessageNotFound Code = "MessageNotFound"
MessageTooLarge Code = "MessageTooLarge"
PopReceiptMismatch Code = "PopReceiptMismatch"
)Usage:
// Handle message deletion
_, err := queueClient.DeleteMessage(context.TODO(), messageID, popReceipt, nil)
if queueerror.HasCode(err, queueerror.MessageNotFound) {
fmt.Println("Message already deleted or expired")
} else if queueerror.HasCode(err, queueerror.PopReceiptMismatch) {
fmt.Println("PopReceipt is invalid - message may have been updated")
} else if err != nil {
return err
}
// Handle message enqueue
_, err = queueClient.EnqueueMessage(context.TODO(), largeContent, nil)
if queueerror.HasCode(err, queueerror.MessageTooLarge) {
fmt.Println("Message exceeds 64 KiB size limit")
}const (
InvalidHTTPVerb Code = "InvalidHttpVerb"
InvalidHeaderValue Code = "InvalidHeaderValue"
InvalidInput Code = "InvalidInput"
InvalidMD5 Code = "InvalidMd5"
InvalidMarker Code = "InvalidMarker"
InvalidMetadata Code = "InvalidMetadata"
InvalidQueryParameterValue Code = "InvalidQueryParameterValue"
InvalidRange Code = "InvalidRange"
InvalidResourceName Code = "InvalidResourceName"
InvalidURI Code = "InvalidUri"
InvalidXMLDocument Code = "InvalidXmlDocument"
InvalidXMLNodeValue Code = "InvalidXmlNodeValue"
MD5Mismatch Code = "Md5Mismatch"
)Usage:
if queueerror.HasCode(err,
queueerror.InvalidResourceName,
queueerror.InvalidInput) {
fmt.Println("Invalid queue name or parameters")
}
if queueerror.HasCode(err, queueerror.InvalidMetadata) {
fmt.Println("Metadata contains invalid characters or exceeds size limit")
}const (
EmptyMetadataKey Code = "EmptyMetadataKey"
MetadataTooLarge Code = "MetadataTooLarge"
)Usage:
_, err := queueClient.SetMetadata(context.TODO(), &azqueue.SetMetadataOptions{
Metadata: metadata,
})
if queueerror.HasCode(err, queueerror.EmptyMetadataKey) {
fmt.Println("Metadata key cannot be empty")
} else if queueerror.HasCode(err, queueerror.MetadataTooLarge) {
fmt.Println("Metadata exceeds maximum size (8 KB)")
}const (
MissingContentLengthHeader Code = "MissingContentLengthHeader"
MissingRequiredHeader Code = "MissingRequiredHeader"
MissingRequiredQueryParameter Code = "MissingRequiredQueryParameter"
MissingRequiredXMLNode Code = "MissingRequiredXmlNode"
RequestBodyTooLarge Code = "RequestBodyTooLarge"
RequestURLFailedToParse Code = "RequestUrlFailedToParse"
)const (
ResourceAlreadyExists Code = "ResourceAlreadyExists"
ResourceNotFound Code = "ResourceNotFound"
ResourceTypeMismatch Code = "ResourceTypeMismatch"
)Usage:
if queueerror.HasCode(err, queueerror.ResourceNotFound) {
fmt.Println("Resource not found")
}const (
ConditionHeadersNotSupported Code = "ConditionHeadersNotSupported"
ConditionNotMet Code = "ConditionNotMet"
MultipleConditionHeadersNotSupported Code = "MultipleConditionHeadersNotSupported"
)const (
FeatureVersionMismatch Code = "FeatureVersionMismatch"
InternalError Code = "InternalError"
OperationTimedOut Code = "OperationTimedOut"
OutOfRangeInput Code = "OutOfRangeInput"
OutOfRangeQueryParameterValue Code = "OutOfRangeQueryParameterValue"
ServerBusy Code = "ServerBusy"
UnsupportedHTTPVerb Code = "UnsupportedHttpVerb"
UnsupportedHeader Code = "UnsupportedHeader"
UnsupportedQueryParameter Code = "UnsupportedQueryParameter"
UnsupportedXMLNode Code = "UnsupportedXmlNode"
)Usage:
if queueerror.HasCode(err, queueerror.ServerBusy) {
// Implement exponential backoff retry
fmt.Println("Server busy - retrying after delay")
}
if queueerror.HasCode(err, queueerror.OperationTimedOut) {
fmt.Println("Operation timed out - retry operation")
}
if queueerror.HasCode(err, queueerror.InternalError) {
fmt.Println("Internal server error - retry operation")
}import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/v2"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azqueue/v2/queueerror"
)
func ensureQueueExists(client *azqueue.QueueClient) error {
_, err := client.Create(context.TODO(), nil)
if err == nil {
return nil // Successfully created
}
if queueerror.HasCode(err, queueerror.QueueAlreadyExists) {
return nil // Already exists - success
}
return err // Other error
}func safeDeleteQueue(client *azqueue.QueueClient) error {
_, err := client.Delete(context.TODO(), nil)
if err == nil {
return nil // Successfully deleted
}
// Ignore if queue doesn't exist or is already being deleted
if queueerror.HasCode(err,
queueerror.QueueNotFound,
queueerror.QueueBeingDeleted) {
return nil
}
return err // Other error
}func processMessage(client *azqueue.QueueClient) error {
// Dequeue message
resp, err := client.DequeueMessage(context.TODO(), nil)
if err != nil {
return fmt.Errorf("dequeue failed: %w", err)
}
if len(resp.Messages) == 0 {
return nil // No messages available
}
msg := resp.Messages[0]
// Process message...
processErr := processMessageContent(*msg.MessageText)
if processErr != nil {
// Processing failed - message will become visible again
return processErr
}
// Delete message after successful processing
_, err = client.DeleteMessage(
context.TODO(),
*msg.MessageID,
*msg.PopReceipt,
nil,
)
if queueerror.HasCode(err, queueerror.MessageNotFound) {
// Message already deleted or expired - not an error
return nil
}
if queueerror.HasCode(err, queueerror.PopReceiptMismatch) {
// PopReceipt invalid - message was updated by another process
return fmt.Errorf("message was modified by another process")
}
return err
}
func processMessageContent(content string) error {
// Application-specific processing logic
return nil
}import (
"time"
"math"
)
func enqueueWithRetry(client *azqueue.QueueClient, content string, maxRetries int) error {
var lastErr error
for attempt := 0; attempt < maxRetries; attempt++ {
_, err := client.EnqueueMessage(context.TODO(), content, nil)
if err == nil {
return nil // Success
}
// Check if error is retryable
if queueerror.HasCode(err,
queueerror.ServerBusy,
queueerror.OperationTimedOut,
queueerror.InternalError) {
lastErr = err
// Exponential backoff: 100ms, 200ms, 400ms, 800ms, ...
backoff := time.Duration(math.Pow(2, float64(attempt))) * 100 * time.Millisecond
time.Sleep(backoff)
continue
}
// Non-retryable error
return err
}
return fmt.Errorf("max retries exceeded: %w", lastErr)
}import (
"fmt"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
)
func handleError(err error) {
if err == nil {
return
}
// Check if it's an Azure service error
var respErr *azcore.ResponseError
if errors.As(err, &respErr) {
fmt.Printf("Azure error occurred:\n")
fmt.Printf(" Error Code: %s\n", respErr.ErrorCode)
fmt.Printf(" Status Code: %d\n", respErr.StatusCode)
fmt.Printf(" Message: %s\n", respErr.Error())
// Check specific error codes
if queueerror.HasCode(err, queueerror.AuthenticationFailed) {
fmt.Println(" -> Check your credentials")
} else if queueerror.HasCode(err, queueerror.QueueNotFound) {
fmt.Println(" -> Queue does not exist")
} else if queueerror.HasCode(err, queueerror.MessageTooLarge) {
fmt.Println(" -> Message exceeds 64 KiB limit")
}
} else {
// Not an Azure service error
fmt.Printf("Error: %v\n", err)
}
}queueerror.HasCode() instead of string comparison for error codes// Multiple processes trying to create the same queue
_, err := queueClient.Create(context.TODO(), nil)
if err != nil && !queueerror.HasCode(err, queueerror.QueueAlreadyExists) {
return err
}
// Continue - queue exists// Another worker may have already processed the message
_, err := queueClient.DeleteMessage(context.TODO(), messageID, popReceipt, nil)
if err != nil && !queueerror.HasCode(err, queueerror.MessageNotFound) {
return err
}
// Continue - message deleted_, err := queueClient.EnqueueMessage(context.TODO(), content, nil)
if queueerror.HasCode(err,
queueerror.AuthenticationFailed,
queueerror.AuthorizationFailure) {
return errors.New("SAS token is invalid or expired")
}if queueerror.HasCode(err, queueerror.AuthorizationSourceIPMismatch) {
return errors.New("request originated from unauthorized IP address")
}