getsops/sops · error

could not parse %q into a valid Azure Key Vault MasterKey %v

Error message

could not parse %q into a valid Azure Key Vault MasterKey %v

What it means

NewMasterKeyFromURL parses an Azure Key Vault key URL of the form {vaultUrl}/keys/{keyName}/{keyVersion}. This error means the URL did not match that pattern, so a MasterKey cannot be constructed from it.

Source

Thrown at azkv/keysource.go:101

// NewMasterKey creates a new MasterKey from a URL, key name and (optional) version,
// setting the creation date to the current date.
func NewMasterKeyWithOptionalVersion(vaultURL string, keyName string, keyVersion string) (*MasterKey, error) {
	key := newMasterKey(vaultURL, keyName, keyVersion)
	if err := key.ensureKeyHasVersion(context.Background()); err != nil {
		return nil, err
	}
	return key, nil
}

// NewMasterKeyFromURL takes an Azure Key Vault key URL, and returns a new
// MasterKey. The URL format is {vaultUrl}/keys/{keyName}/{keyVersion}.
func NewMasterKeyFromURL(url string) (*MasterKey, error) {
	url = strings.TrimSpace(url)
	re := regexp.MustCompile("^(https://[^/]+)/keys/([^/]+)(/[^/]*)?$")
	parts := re.FindStringSubmatch(url)
	if len(parts) < 3 {
		return nil, fmt.Errorf("could not parse %q into a valid Azure Key Vault MasterKey %v", url, parts)
	}
	// Blank key versions are supported in Azure Key Vault, as they default to the latest
	// version of the key. We need to put the actual version in the sops metadata block though
	var key *MasterKey
	if len(parts[3]) > 1 {
		key = newMasterKey(parts[1], parts[2], parts[3][1:])
	} else {
		key = newMasterKey(parts[1], parts[2], "")
	}
	err := key.ensureKeyHasVersion(context.Background())
	return key, err
}

// MasterKeysFromURLs takes a comma separated list of Azure Key Vault URLs,
// and returns a slice of new MasterKeys.
func MasterKeysFromURLs(urls string) ([]*MasterKey, error) {
	var keys []*MasterKey
	if urls == "" {

View on GitHub (pinned to 13442bb981)

Solutions

  1. Use the full key identifier copied from the Azure portal: https://<vault-name>.vault.azure.net/keys/<key-name>/<key-version>
  2. Ensure the scheme is exactly https:// and there is no trailing slash issue or extra query string
  3. Verify the URL contains the literal /keys/ segment followed by a non-empty key name
  4. Trim whitespace/newlines if the URL came from a file or env var

Example fix

// before
https://myvault.vault.azure.net/keys/           # missing key name
// after
https://myvault.vault.azure.net/keys/my-sops-key/1234abcd
Defensive patterns

Strategy: validation

Validate before calling

var azKeyURLRe = regexp.MustCompile(`^https://[^/]+/keys/[^/]+(/[^/]*)?$`)
func validateAzureKVURL(u string) error {
    u = strings.TrimSpace(u)
    if !azKeyURLRe.MatchString(u) {
        return fmt.Errorf("invalid Azure KV key URL: %q (want https://vault/keys/name/version)", u)
    }
    return nil
}

Type guard

func isWellFormedAzureKeyURL(u string) bool {
    u = strings.TrimSpace(u)
    re := regexp.MustCompile(`^https://[^/]+/keys/[^/]+(/[^/]*)?$`)
    return re.MatchString(u)
}

Try / catch

k, err := azkv.NewMasterKeyFromURL(u)
if err != nil {
    return fmt.Errorf("bad azure_kv entry %q: %w", u, err)
}

Prevention

When it happens

Trigger: Calling NewMasterKeyFromURL or MasterKeysFromURLs with a string missing https://, missing /keys/, missing key name, or containing unexpected whitespace/newlines that survive trimming.

Common situations: Copying a key ID from the Azure portal that uses vault:// or an incomplete path; forgetting the https:// scheme; using a managed-HSM URL with /keys under a different path shape; typos or extra query parameters; pasting a multi-line list into the sops config.

Related errors


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