argoproj/argo-workflows · critical

failed to obtain a credential: %w

Error message

failed to obtain a credential: %w

What it means

azureConnector.Connect obtains an Azure credential chain via azidentity.NewDefaultAzureCredential (environment, workload identity, managed identity, Azure CLI, etc.). If none of the credential types in the chain can be constructed, Connect wraps the azidentity error with "failed to obtain a credential". It means no Azure authentication source is available to the process at all.

Source

Thrown at util/sqldb/azure_auth.go:22

	"context"
	"database/sql/driver"
	"fmt"
	"strings"

	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
	"github.com/lib/pq"
)

type azureConnector struct {
	dsn   string
	scope string
}

func (c *azureConnector) Connect(ctx context.Context) (driver.Conn, error) {
	cred, err := azidentity.NewDefaultAzureCredential(nil)
	if err != nil {
		return nil, fmt.Errorf("failed to obtain a credential: %w", err)
	}

	token, err := cred.GetToken(ctx, policy.TokenRequestOptions{Scopes: []string{c.scope}})
	if err != nil {
		return nil, fmt.Errorf("failed to get token: %w", err)
	}

	// Escape single quotes in token just in case
	escapedToken := strings.ReplaceAll(token.Token, "'", "\\'")

	// Append password to DSN
	dsnWithPassword := fmt.Sprintf("%s password='%s'", c.dsn, escapedToken)

	return pq.Driver{}.Open(dsnWithPassword)
}

func (c *azureConnector) Driver() driver.Driver {
	return pq.Driver{}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Configure workload identity: add the azure.workload.identity/use label and azure-client-id/tenant-id annotations to the pod, ensuring AZURE_FEDERATED_TOKEN_FILE and AZURE_AUTHORITY_HOST are injected.
  2. Alternatively set the full environment credential trio consistently: AZURE_TENANT_ID, AZURE_CLIENT_ID, and either AZURE_CLIENT_SECRET or AZURE_CLIENT_CERTIFICATE_PATH.
  3. For local dev, run `az login` so the Azure CLI credential in the chain succeeds.
  4. If only managed identity should be used, ensure the pod/VM runs on Azure infrastructure with that identity assigned.
  5. Read the wrapped azidentity error — it lists which credential in the chain failed and why.

Example fix

// before (incomplete env)
AZURE_CLIENT_ID=xxx  // tenant missing
// after
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/azure/tokens/azure-identity-token
Defensive patterns

Strategy: validation

Validate before calling

required := []string{"AZURE_TENANT_ID", "AZURE_CLIENT_ID"}
for _, k := range required {
    if os.Getenv(k) == "" && os.Getenv("AZURE_FEDERATED_TOKEN_FILE") == "" {
        return fmt.Errorf("%s missing and no workload identity configured", k)
    }
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "failed to obtain a credential") {
        // credential chain empty: fix env/identity, don't retry
        return fmt.Errorf("azure credential chain unavailable: %w", err)
    }
}

Prevention

When it happens

Trigger: Calling Connect on azureConnector when NewDefaultAzureCredential(nil) fails: AZURE_TENANT_ID/AZURE_CLIENT_ID/AZURE_CLIENT_CERTIFICATE_PATH or client secret env vars are partially/inconsistently set, workload identity env vars missing (AZURE_FEDERATED_TOKEN_FILE, AZURE_AUTHORITY_HOST), and managed identity / CLI credentials are unavailable in the environment.

Common situations: Running Argo locally outside Azure with no az login; pod without the azure workload-identity labels/annotation or missing the projected federated token file; AZURE_CLIENT_ID set without AZURE_TENANT_ID; upgrading azidentity changes which chain members are attempted.

Related errors


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