{"record":{"id":"5cf23ec9d975fe39","repo":"hashicorp/terraform","slug":"sastoken-cannot-be-empty","errorCode":null,"errorMessage":"sasToken cannot be empty","messagePattern":"sasToken cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/azure/api_client.go","lineNumber":57,"sourceCode":"\taccessKey          string\n\tsasToken           string\n\tazureAdStorageAuth auth.Authorizer\n}\n\nfunc buildClient(ctx context.Context, config BackendConfig) (*Client, error) {\n\tclient := Client{\n\t\tenvironment:        config.AuthConfig.Environment,\n\t\tstorageAccountName: config.StorageAccountName,\n\t}\n\n\tvar armAuthRequired bool\n\tswitch {\n\tcase config.AccessKey != \"\":\n\t\tclient.accessKey = config.AccessKey\n\tcase config.SasToken != \"\":\n\t\tsasToken := config.SasToken\n\t\tif strings.TrimSpace(sasToken) == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"sasToken cannot be empty\")\n\t\t}\n\t\tclient.sasToken = strings.TrimPrefix(sasToken, \"?\")\n\tcase config.UseAzureADAuthentication:\n\t\tvar err error\n\t\tclient.azureAdStorageAuth, err = auth.NewAuthorizerFromCredentials(ctx, *config.AuthConfig, config.AuthConfig.Environment.Storage)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to build authorizer for Storage API: %+v\", err)\n\t\t}\n\tdefault:\n\t\t// AAD authentication (ARM scope) is required only when no auth method is specified, which falls back to listing the access key via ARM API.\n\t\tarmAuthRequired = true\n\t}\n\n\t// If `config.LookupBlobEndpoint` is true, we need to authenticate with ARM to lookup the blob endpoint\n\tif config.LookupBlobEndpoint {\n\t\tarmAuthRequired = true\n\t}\n","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/azure/api_client.go#L39-L75","documentation":"Returned by buildClient when the Azure backend is configured with a sasToken that, after whitespace trimming, is empty. The config indicated SAS auth (config.SasToken != \"\") but the actual token content is blank/whitespace-only, so it is rejected before use.","triggerScenarios":"Setting sas_token in the azurerm backend block (or ARM_SAS_TOKEN env var) to an empty string or whitespace while the non-empty check passed due to leading characters. Most directly: config.SasToken is non-empty but strings.TrimSpace yields empty.","commonSituations":"ARM_SAS_TOKEN env var set to spaces/quotes only; sas_token = \"\" with accidental characters; CI secret not populated resulting in a blank value; copy-paste of the key with only the leading '?' or quotes stripped.","solutions":["Provide a valid, non-empty SAS token value in the backend block or ARM_SAS_TOKEN environment variable.","Verify the CI/CD secret actually populates ARM_SAS_TOKEN (print its length, not its value).","Strip only a leading '?' if present; ensure the remaining token has content."],"exampleFix":"# before\nexport ARM_SAS_TOKEN=\"\"\n# after\nexport ARM_SAS_TOKEN=\"sv=2021-06-08&ss=bfqt&srt=sco...\"","handlingStrategy":"validation","validationCode":"sas := strings.TrimSpace(config.SasToken)\nif config.SasToken != \"\" && sas == \"\" {\n    return errors.New(\"sas_token is set but empty after trimming; provide a real SAS token\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate that ARM_SAS_TOKEN is populated (check length, not value) in CI before terraform init.","Store the SAS token in a secret manager rather than hardcoding possibly-empty values.","Use a config linter that rejects whitespace-only secret values."],"tags":["azure","backend","auth","sas-token","config","terraform"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}