juicedata/juicefs · error

Failed to create Azure blob client with SAS token: %v

Error message

Failed to create Azure blob client with SAS token: %v

What it means

Thrown when azblob.NewClientWithNoCredential cannot construct an azblob.Client from the SAS URL (<scheme>://<account>.<domain>?<sas>). This happens after endpoint discovery succeeded, and indicates the assembled SAS URL is malformed.

Source

Thrown at pkg/object/azure.go:345

	// Priority 2: No account key — use SAS token or managed identity
	if accountKey == "" {
		domain := domainFromHost(hostParts)

		normalized := normalizeSASToken(token)

		if normalized != "" {
			if domain == "" {
				var err error
				if domain, err = autoWasbEndpoint(accountName, uri.Scheme, func(serviceURL string) (*azblob.Client, error) {
					return azblob.NewClientWithNoCredential(serviceURL+"?"+normalized, nil)
				}); err != nil {
					return nil, fmt.Errorf("Unable to get endpoint of container %s: %s", containerName, err)
				}
			}
			sasURL := fmt.Sprintf("%s://%s.%s?%s", uri.Scheme, accountName, domain, normalized)
			client, err := azblob.NewClientWithNoCredential(sasURL, azblobOptions())
			if err != nil {
				return nil, fmt.Errorf("Failed to create Azure blob client with SAS token: %v", err)
			}
			return &wasb{container: client.ServiceClient().NewContainerClient(containerName), azblobCli: client, cName: containerName, useTokenAuth: true}, nil
		}

		tokenCred, err := createAzureCredential()
		if err != nil {
			return nil, fmt.Errorf("Failed to create Azure credential (managed identity/Azure CLI): %v", err)
		}
		if domain == "" {
			if domain, err = autoWasbEndpoint(accountName, uri.Scheme, func(serviceURL string) (*azblob.Client, error) {
				return azblob.NewClient(serviceURL, tokenCred, nil)
			}); err != nil {
				return nil, fmt.Errorf("Unable to get endpoint of container %s: %s", containerName, err)
			}
		}
		serviceURL := fmt.Sprintf("%s://%s.%s", uri.Scheme, accountName, domain)
		client, err := azblob.NewClient(serviceURL, tokenCred, azblobOptions())
		if err != nil {

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Inspect the SAS token for whitespace, quotes, or a leading '?'; trim/normalize it.
  2. Provide the endpoint with an explicit full domain so a bad auto-discovered domain is not used.
  3. Validate the final URL parses with url.Parse before constructing the client.
  4. Regenerate the SAS token from the Azure portal/CLI.

Example fix

// before
endpoint: "azblob://acct.blob.core.windows.net? token=sv=..."  (space inside token)
// after
endpoint: "azblob://acct.blob.core.windows.net?sv=2020-02-10&ss=b&srt=sco"
Defensive patterns

Strategy: validation

Validate before calling

sas := strings.TrimSpace(sasToken)
sas = strings.TrimPrefix(sas, "?")
if sas == "" { return errors.New("empty SAS token") }
if _, err := url.Parse("https://acct.blob.core.windows.net?" + sas); err != nil { return err }

Try / catch

client, err := azblob.NewClientWithNoCredential(sasURL, nil)
if err != nil {
    return fmt.Errorf("bad SAS URL %q: %w", redact(sasURL), err)
}

Prevention

When it happens

Trigger: newWasb with SAS auth where the discovered domain combined with the account name and SAS query produces a URL the SDK rejects (empty/invalid domain discovered, invalid characters in SAS token).

Common situations: SAS token copied with stray whitespace/newlines; SAS token missing leading '?'; auto-discovered domain empty or garbage; non-URL-safe characters pasted from config files.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/4f3adcd6dab91b42. Report an issue: GitHub.