{"record":{"id":"10f9e30929f4faf2","repo":"bytebase/bytebase","slug":"missing-azure-key-vault-url","errorCode":null,"errorMessage":"missing Azure Key Vault URL","messagePattern":"missing Azure Key Vault URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/component/secret/azure.go","lineNumber":29,"sourceCode":"\tstorepb \"github.com/bytebase/bytebase/backend/generated-go/store\"\n)\n\nfunc getSecretFromAzure(ctx context.Context, externalSecret *storepb.DataSourceExternalSecret) (string, error) {\n\t// Use default Azure credentials.\n\t// This supports:\n\t// - Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID)\n\t// - Managed Identity (when running in Azure)\n\t// - Azure CLI credentials\n\t// ref: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DefaultAzureCredential\n\tcred, err := azidentity.NewDefaultAzureCredential(nil)\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"failed to get Azure credentials\")\n\t}\n\n\t// The URL should be the Key Vault URL (e.g., https://myvault.vault.azure.net/)\n\tvaultURL := externalSecret.Url\n\tif vaultURL == \"\" {\n\t\treturn \"\", errors.New(\"missing Azure Key Vault URL\")\n\t}\n\n\tclient, err := azsecrets.NewClient(vaultURL, cred, nil)\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"failed to create Azure Key Vault client\")\n\t}\n\n\t// Get the secret using the secret name.\n\t// Empty version string means get the latest version.\n\tresp, err := client.GetSecret(ctx, externalSecret.SecretName, \"\", nil)\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"SecretNotFound\") {\n\t\t\treturn \"\", errors.Wrapf(err, \"cannot find secret %s\", externalSecret.SecretName)\n\t\t}\n\t\treturn \"\", errors.Wrapf(err, \"failed to get Azure Key Vault secret %s\", externalSecret.SecretName)\n\t}\n\n\tif resp.Value == nil {","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/component/secret/azure.go#L11-L47","documentation":"When resolving an external secret stored in Azure Key Vault, the component obtains Azure credentials and then reads the vault endpoint from externalSecret.Url. If Url is empty it cannot construct an azsecrets client, so getSecretFromAzure fails with 'missing Azure Key Vault URL' before any network call.","triggerScenarios":"ReplaceExternalSecret dispatches to the Azure provider but the ExternalSecret record was saved without Url populated (the Key Vault URL such as https://myvault.vault.azure.net/).","commonSituations":"Creating the external secret via API/UI and leaving the vault URL field blank; copying config from an AWS/GCP secret setup where no URL is needed; a migration that dropped the Url field.","solutions":["Set externalSecret.Url to the full Key Vault URL, e.g. https://<vault-name>.vault.azure.net/.","Confirm the URL is reachable and uses https:// (azsecrets.NewClient requires a valid vault endpoint).","Check that the correct provider (Azure) is selected for this secret, not AWS/GCP which use different identifiers.","Re-save the ExternalSecret record and retry ReplaceExternalSecret."],"exampleFix":"// before\n{\"provider\": \"AZURE\", \"url\": \"\"}\n// after\n{\"provider\": \"AZURE\", \"url\": \"https://myvault.vault.azure.net/\"}","handlingStrategy":"validation","validationCode":"if (externalSecret.provider === 'AZURE' && !externalSecret.url) {\n  throw new Error('Azure external secret requires the Key Vault URL, e.g. https://myvault.vault.azure.net/')\n}\nawait replaceExternalSecret(externalSecret)","typeGuard":"func azureSecretURLValid(s ExternalSecret) bool {\n\treturn s.Provider == Azure && strings.HasPrefix(s.Url, \"https://\") && strings.HasSuffix(s.Url, \"/\")\n}","tryCatchPattern":"secret, err := manager.ReplaceExternalSecret(ctx, ext)\nif err != nil && strings.Contains(err.Error(), \"missing Azure Key Vault URL\") {\n  return fmt.Errorf(\"external secret %q: set the vault URL field before syncing\", ext.Name)\n}","preventionTips":["Make the vault URL a required form field when the Azure provider is selected.","Store the full https://<vault>.vault.azure.net/ URL, not just the vault name.","Validate external-secret records on save so no provider dispatch ever sees an empty URL."],"tags":["azure","key-vault","secrets","config"],"backgroundTag":"missing-required-config-field","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}