argoproj/argo-workflows · error

unable to create Azure shared key credential: %w

Error message

unable to create Azure shared key credential: %w

What it means

After endpoint parsing and account-name detection, the driver builds an azblob.NewSharedKeyCredential(accountName, accountKey); azidentity rejects keys that are not valid base64-encoded 64-byte storage keys, producing this wrapped error.

Source

Thrown at workflow/artifacts/azure/azure.go:78

	if azblobDriver.AccountKey == "" {
		return nil, fmt.Errorf("accountKey secret is required for Azure Blob Storage if useSDKCreds is false")
	}

	if isSASAccountKey(azblobDriver.AccountKey) {
		logger := logging.RequireLoggerFromContext(ctx)
		logger.Info(ctx, "Provided account key is a SAS token. Using no-credential client.")
		serviceURL := fmt.Sprintf("%s?%s", containerURL.String(), azblobDriver.AccountKey)
		containerClient, clientErr := container.NewClientWithNoCredential(serviceURL, nil)
		return containerClient, clientErr
	}

	accountName, err := determineAccountName(containerURL)
	if err != nil {
		return nil, err
	}
	credential, err := azblob.NewSharedKeyCredential(accountName, azblobDriver.AccountKey)
	if err != nil {
		return nil, fmt.Errorf("unable to create Azure shared key credential: %w", err)
	}
	containerClient, err := container.NewClientWithSharedKeyCredential(containerURL.String(), credential, nil)
	return containerClient, err
}

// determineAccountName determines the account name of the storage account based on the
// supplied container URL.
func determineAccountName(containerURL *url.URL) (string, error) {
	hostname := containerURL.Hostname()
	if strings.HasPrefix(hostname, "127.0.0.1") || strings.HasPrefix(hostname, "localhost") {
		parts := strings.Split(containerURL.Path, "/")
		if len(parts) <= 2 {
			return "", fmt.Errorf("unable to determine storage account name from %s", containerURL)
		}
		return parts[1], nil
	}
	parts := strings.Split(hostname, ".")
	return parts[0], nil

View on GitHub (pinned to 35bff19146)

Solutions

  1. Copy only the raw base64 'key' value from the Azure portal (Storage account → Access keys), not the connection string or SAS token.
  2. If authenticating with a SAS token, append it to the endpoint URL instead of accountKey so the no-credential path is used.
  3. Ensure the endpoint hostname encodes the account name (e.g. https://<account>.blob.core.windows.net) so determineAccountName succeeds.
  4. Check for trailing whitespace/newlines in the secret value.

Example fix

// before — accountKey secret
account-key: DefaultEndpointsProtocol=https;AccountName=acct;AccountKey=abc...==
// after — key only
account-key: abc...base64key...==
Defensive patterns

Strategy: validation

Validate before calling

func validateAccountKey(key string) error {
	b, err := base64.StdEncoding.DecodeString(strings.TrimSpace(key))
	if err != nil || len(b) != 64 {
		return fmt.Errorf("accountKey must be the base64 storage access key (64 decoded bytes), not a connection string or SAS token")
	}
	return nil
}

Try / catch

credential, err := azblob.NewSharedKeyCredential(accountName, key)
if err != nil {
	return fmt.Errorf("check accountKey value (base64 key only, not connection string/SAS): %w", err)
}

Prevention

When it happens

Trigger: accountKey is not a valid base64 storage account key (e.g. it is actually a SAS token that failed the isSASAccountKey heuristic, a connection string, or a truncated/whitespace-corrupted key), or accountName derived from the endpoint is empty.

Common situations: Pasted a SAS token into accountKey where it wasn't recognized as such; used the connection string instead of just the key; account name could not be derived from a custom-domain endpoint.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/e50ee0b8a11018ef. Report an issue: GitHub.