getsops/sops · error

failed to fetch Azure Key to retrieve key version: %w

Error message

failed to fetch Azure Key to retrieve key version: %w

What it means

ensureKeyHasVersion calls c.GetKey to fetch the key and derive its version when the URL omitted one. This error means the KeyVault GetKey REST call failed — the key doesn't exist, the credential lacks permission, or the request couldn't reach the vault.

Source

Thrown at azkv/keysource.go:195

	}

	token, err := key.getTokenCredential()

	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Encryption failed")
		return fmt.Errorf("failed to get Azure token credential to retrieve key version: %w", err)
	}

	c, err := azkeys.NewClient(key.VaultURL, token, key.clientOptions)
	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Encryption failed")
		return fmt.Errorf("failed to construct Azure Key Vault client to retrieve key version: %w", err)
	}

	kdetail, err := c.GetKey(ctx, key.Name, key.Version, nil)
	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Encryption failed")
		return fmt.Errorf("failed to fetch Azure Key to retrieve key version: %w", err)
	}
	key.Version = kdetail.Key.KID.Version()

	log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Version fetch succeeded")
	return nil
}

// EncryptContext takes a SOPS data key, encrypts it with Azure Key Vault, and stores
// the result in the EncryptedKey field.
func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error {
	token, err := key.getTokenCredential()
	if err != nil {
		log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Encryption failed")
		return fmt.Errorf("failed to get Azure token credential to encrypt data: %w", err)
	}

	c, err := azkeys.NewClient(key.VaultURL, token, key.clientOptions)
	if err != nil {

View on GitHub (pinned to 13442bb981)

Solutions

  1. Grant the identity the Key Vault 'get' key permission / 'Key Vault Crypto User' role via an access policy or RBAC
  2. Verify the key name and vault are correct: az keyvault key show --vault-name <vault> -n <name>
  3. Check the vault's network rules/firewall allow the caller's IP or VNet
  4. Confirm the token scope with az account get-access-token --resource https://vault.azure.net

Example fix

# before: principal has no access
az keyvault set-policy -n myvault --spn <client-id> --key-permissions get encrypt decrypt
# after: retry sops with granted permissions
Defensive patterns

Strategy: retry

Validate before calling

// preflight: confirm identity can read the key
out, err := exec.Command("az", "keyvault", "key", "show", "--vault-name", vault, "-n", keyName).CombinedOutput()
if err != nil {
    return fmt.Errorf("key %s/%s not accessible: %s", vault, keyName, out)
}

Try / catch

err := sopsRun(...)
if strings.Contains(err.Error(), "failed to fetch Azure Key") {
    var respErr *azcore.ResponseError
    if errors.As(err, &respErr) && respErr.StatusCode == 403 {
        return fmt.Errorf("grant the identity 'get' key permission / Key Vault Crypto User role: %w", err)
    }
    return err // 404: fix key name; network: retry
}

Prevention

When it happens

Trigger: ensureKeyHasVersion (from NewMasterKeyFromURL) invokes c.GetKey(ctx, key.Name, key.Version, nil) and receives an error: 403 from missing 'get' key permission, 404 unknown key name, network failure, or expired/insufficient token scope.

Common situations: Service principal without Key Vault 'Key Vault Crypto User'/'get' role; key name typo in .sops.yaml; vault firewall blocking the client IP; key deleted or purged; private-link/DNS issues.

Related errors


AI-assisted analysis of getsops/sops@13442bb981 (2026-09-01). Data as JSON: /api/errors/9aee67c965086114. Report an issue: GitHub.