argoproj/argo-workflows · error

unable to upload file %s to Azure: %w

Error message

unable to upload file %s to Azure: %w

What it means

Fired in ArtifactDriver.Save while uploading a single file to Azure Blob Storage: PutFile (or the preceding client/dir logic) failed and the error is wrapped with the local path. Indicates Azure-side rejection, auth, or network trouble during artifact save.

Source

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

	isDir, err := file.IsDirectory(path)
	if err != nil {
		return fmt.Errorf("failed to test if %s is a directory: %w", path, err)
	}

	containerClient, err := azblobDriver.newAzureContainerClient(ctx)
	if err != nil {
		return fmt.Errorf("unable to create Azure Blob Container client for %s: %w", outputArtifact.Azure.Blob, err)
	}

	if isDir {
		err := PutDirectory(ctx, containerClient, outputArtifact.Azure.Blob, path)
		if err != nil {
			return fmt.Errorf("unable to upload directory %s to Azure: %w", path, err)
		}
	} else {
		err := PutFile(ctx, containerClient, outputArtifact.Azure.Blob, path)
		if err != nil {
			return fmt.Errorf("unable to upload file %s to Azure: %w", path, err)
		}
	}

	return nil
}

// SaveStream saves an artifact from an io.Reader to Azure Blob Storage
func (azblobDriver *ArtifactDriver) SaveStream(ctx context.Context, reader io.Reader, outputArtifact *wfv1.Artifact) error {
	logger := logging.RequireLoggerFromContext(ctx)
	logger.WithField("endpoint", outputArtifact.Azure.Endpoint).
		WithField("container", outputArtifact.Azure.Container).
		WithField("blob", outputArtifact.Azure.Blob).
		Info(ctx, "Streaming to Azure Blob Storage")

	containerClient, err := azblobDriver.newAzureContainerClient(ctx)
	if err != nil {
		return fmt.Errorf("unable to create Azure Blob Container client for %s: %w", outputArtifact.Azure.Blob, err)
	}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Read the wrapped inner error to distinguish local open failure vs Azure upload failure.
  2. If local: fix permissions/existence of the artifact path.
  3. If Azure: check credentials, retries, and blob size limits; split large files.
  4. Verify container-level write permissions for the account key.
  5. Retry on transient network/storage errors.

Example fix

// before: unreadable file saved as artifact
cmd: [sh, -c, "umask 077; generate > /work/out.txt"]
// after: ensure readable by executor user
cmd: [sh, -c, "generate > /work/out.txt && chmod 644 /work/out.txt"]
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil {
  return fmt.Errorf("artifact file missing: %w", err)
}
if info.Size() > 195*1024*1024*1024 {
  return errors.New("file exceeds Azure block blob limit")
}

Type guard

func isUploadErr(err error) bool {
  return errors.As(err, new(*azcore.ResponseError))
}

Try / catch

err := driver.Save(ctx, path, artifact)
if err != nil && strings.Contains(err.Error(), "unable to upload file") {
  var re *azcore.ResponseError
  if errors.As(errors.Unwrap(err), &re) && re.StatusCode >= 500 {
    // retry with backoff
  }
  return err
}

Prevention

When it happens

Trigger: Saving a file artifact when os.Open fails (permission, disappeared mid-run) or blobClient.UploadFile fails (auth, network, quota, oversized blob).

Common situations: File deleted between generation and save; read-permission problems for the emissary user; single blob exceeding 195GB block-blob limit; transient network errors.

Related errors


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