apache/druid · error · ISE

Set only one of 'key' or 'sharedAccessStorageToken' or 'useA

Error message

Set only one of 'key' or 'sharedAccessStorageToken' or 'useAzureCredentialsChain' in the azure config. Please refer to azure documentation.

What it means

This IllegalStateException is thrown at Azure extension startup (AzureClientFactory provider) when the Azure storage configuration defines more than one mutually exclusive authentication mechanism. The deep storage can authenticate with exactly one of: a storage account key ('key'), a shared access storage token ('sharedAccessStorageToken'), or the Azure credentials chain ('useAzureCredentialsChain'). Supplying two or more is ambiguous and rejected immediately during DI initialization.

Source

Thrown at extensions-core/azure-extensions/src/main/java/org/apache/druid/storage/azure/AzureStorageDruidModule.java:135

    if (StringUtils.isEmpty(config.getAccount())) {
      throw new ISE("Set 'account' to the storage account that needs to be configured in the azure config."
          + " Please refer to azure documentation.");
    }

    if (StringUtils.isEmpty(config.getKey()) && StringUtils.isEmpty(config.getSharedAccessStorageToken()) && BooleanUtils.isNotTrue(config.getUseAzureCredentialsChain())) {
      throw new ISE("Either set 'key' or 'sharedAccessStorageToken' or 'useAzureCredentialsChain' in the azure config."
          + " Please refer to azure documentation.");
    }

    /* Azure named keys and sas tokens are mutually exclusive with each other and with azure keychain auth,
    but any form of auth supported by the DefaultAzureCredentialChain is not mutually exclusive, e.g. you can have
    environment credentials or workload credentials or managed credentials using the same chain.
    **/
    if (!StringUtils.isEmpty(config.getKey()) && !StringUtils.isEmpty(config.getSharedAccessStorageToken()) ||
        !StringUtils.isEmpty(config.getKey()) && BooleanUtils.isTrue(config.getUseAzureCredentialsChain()) ||
        !StringUtils.isEmpty(config.getSharedAccessStorageToken()) && BooleanUtils.isTrue(config.getUseAzureCredentialsChain())
    ) {
      throw new ISE("Set only one of 'key' or 'sharedAccessStorageToken' or 'useAzureCredentialsChain' in the azure config."
          + " Please refer to azure documentation.");
    }
    return new AzureClientFactory(config);
  }

  @Provides
  @Global
  @LazySingleton
  public AzureStorage getAzureStorageContainer(
      final AzureClientFactory azureClientFactory,
      final AzureAccountConfig azureAccountConfig
  )
  {
    return new AzureStorage(azureClientFactory, azureAccountConfig.getAccount());
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Inspect the azure config (druid.storage.* properties) and keep exactly one of 'key', 'sharedAccessStorageToken', or 'useAzureCredentialsChain'; remove or blank the others
  2. To switch to managed/workload identity, set azure.useAzureCredentialsChain=true and delete azure.key and azure.sharedAccessStorageToken
  3. To keep static credentials, set exactly one of azure.key or azure.sharedAccessStorageToken and leave useAzureCredentialsChain unset or false
  4. Restart the Druid service and confirm the AzureClientFactory initializes without the ISE

Example fix

// before
{
  "druid.storage.azure.account": "myaccount",
  "druid.storage.azure.key": "<account-key>",
  "druid.storage.azure.useAzureCredentialsChain": true
}
// after
{
  "druid.storage.azure.account": "myaccount",
  "druid.storage.azure.useAzureCredentialsChain": true
}
Defensive patterns

Strategy: validation

Validate before calling

int set = (isEmpty(config.getKey())?0:1) + (isEmpty(config.getSharedAccessStorageToken())?0:1) + (Boolean.TRUE.equals(config.getUseAzureCredentialsChain())?1:0);
if (set > 1) throw new IllegalArgumentException("Set only one of 'key', 'sharedAccessStorageToken', or 'useAzureCredentialsChain'");

Prevention

When it happens

Trigger: Setting both azure.key and azure.sharedAccessStorageToken, or azure.key with azure.useAzureCredentialsChain=true, or azure.sharedAccessStorageToken with azure.useAzureCredentialsChain=true, in the druid.storage.azure config when the AzureStorageDruidModule provider getAzureClientFactory is invoked.

Common situations: Operators migrating from key-based auth to the credentials chain (managed identity / workload identity) who add useAzureCredentialsChain without removing the old key; copy-pasted config snippets that include both a SAS token and an account key; environment-specific config overlays that each set a different credential field, which merge into a combined config.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/8cb7620034251d9d. Report an issue: GitHub.