argoproj/argo-workflows · error

unable to determine storage account name from %s

Error message

unable to determine storage account name from %s

What it means

determineAccountName extracts the storage account from the endpoint URL: for 127.0.0.1/localhost endpoints it takes the first path segment; if the path has two or fewer segments (no account segment present) it fails with this error.

Source

Thrown at workflow/artifacts/azure/azure.go:91

	if err != nil {
		return nil, err
	}
	credential, err := azblob.NewSharedKeyCredential(accountName, azblobDriver.AccountKey)
	if err != nil {
		return nil, fmt.Errorf("unable to create Azure shared key credential: %w", err)
	}
	containerClient, err := container.NewClientWithSharedKeyCredential(containerURL.String(), credential, nil)
	return containerClient, err
}

// determineAccountName determines the account name of the storage account based on the
// supplied container URL.
func determineAccountName(containerURL *url.URL) (string, error) {
	hostname := containerURL.Hostname()
	if strings.HasPrefix(hostname, "127.0.0.1") || strings.HasPrefix(hostname, "localhost") {
		parts := strings.Split(containerURL.Path, "/")
		if len(parts) <= 2 {
			return "", fmt.Errorf("unable to determine storage account name from %s", containerURL)
		}
		return parts[1], nil
	}
	parts := strings.Split(hostname, ".")
	return parts[0], nil
}

// isSASAccountKey determines whether the account key provided is a SAS token instead of a
// storage account key. A SAS token is a string of query parameters that is appended to the
// URL of the storage account. This function looks for the presence of a query parameter in
// the string and returns true if found.
func isSASAccountKey(accountKey string) bool {
	re := regexp.MustCompile(`(\?|\&)([^=]+)\=([^&]+)`)
	return re.MatchString(accountKey)
}

// Load downloads artifacts from Azure Blob Storage
func (azblobDriver *ArtifactDriver) Load(ctx context.Context, artifact *wfv1.Artifact, path string) error {

View on GitHub (pinned to 35bff19146)

Solutions

  1. Include the account name as the first path segment of local endpoints: http://127.0.0.1:10000/devstoreaccount1/<container>.
  2. For real Azure endpoints, use the standard https://<account>.blob.core.windows.net form so the account comes from the hostname.
  3. Test with Argo's documented Azurite endpoint layout before deploying.

Example fix

// before
endpoint: http://127.0.0.1:10000
// after
endpoint: http://127.0.0.1:10000/devstoreaccount1
Defensive patterns

Strategy: validation

Validate before calling

func validateLocalAzureEndpoint(endpoint string) error {
	u, err := url.Parse(endpoint)
	if err != nil { return err }
	h := u.Hostname()
	if strings.HasPrefix(h, "127.0.0.1") || h == "localhost" {
		if len(strings.Split(strings.Trim(u.Path, "/"), "/")) < 1 || strings.Trim(u.Path, "/") == "" {
			return fmt.Errorf("local endpoints must include account path: http://127.0.0.1:10000/<account>")
		}
	}
	return nil
}

Prevention

When it happens

Trigger: Using a local Azurite-style endpoint like http://127.0.0.1:10000 or http://localhost:10000/container without the account path segment; the expected local form is http://127.0.0.1:10000/<account>/<container>.

Common situations: Pointing artifacts at Azurite (local Azure emulator) with the account omitted from the URL; port-forwarding an in-cluster Azure emulator and forgetting the account path prefix.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/cd752b77cc928610. Report an issue: GitHub.