argoproj/argo-workflows · error

Artifact '%s' does not have a storage location configured (s

Error message

Artifact '%s' does not have a storage location configured (s3, gcs, azure, oss). Please configure a storage location in the WorkflowTemplate or set up a default artifact repository.

What it means

After resolving the artifact and attempting to fill in the location from the default artifact repository, UploadInputArtifact checks artifactCopy.HasLocation(). If neither the artifact itself nor any configured default (artifactRepositoryRef, namespace artifact-repositories ConfigMap, or workflow-controller-configmap default artifactRepository) provides an s3/gcs/azure/oss location, the upload is rejected with HTTP 400 because there is nowhere to store the file.

Source

Thrown at server/artifacts/artifact_server.go:224

	// 2. Namespace has artifact-repositories ConfigMap
	// 3. workflow-controller-configmap has default artifactRepository
	// We don't use Relocate() because it requires an existing key, but for uploads we generate a new key anyway.
	if !artifactCopy.HasLocation() {
		archiveLocation, resolveErr := sutils.ResolveArtifactLocation(ctx, a.artifactRepositories, wfTemplate.Spec.ArtifactRepositoryRef, namespace)
		if resolveErr != nil {
			a.logger.WithError(resolveErr).Debug(ctx, "Failed to resolve artifact repository, will check if artifact has location anyway")
		} else if archiveLocation != nil && archiveLocation.HasLocation() {
			// Copy the location settings (bucket, endpoint, etc.) to our artifact
			artifactCopy.ArtifactLocation = *archiveLocation.DeepCopy()
			a.logger.WithFields(logging.Fields{
				"artifactName": artifactName,
			}).Info(ctx, "Resolved artifact location from default repository")
		}
	}

	// Check if the artifact has a location configured (S3, GCS, etc.)
	if !artifactCopy.HasLocation() {
		http.Error(w, fmt.Sprintf("Artifact '%s' does not have a storage location configured (s3, gcs, azure, oss). Please configure a storage location in the WorkflowTemplate or set up a default artifact repository.", artifactName), http.StatusBadRequest)
		return
	}

	// Generate unique key for the artifact
	uploadUUID := uuid.NewString()
	originalKey, _ := artifactCopy.GetKey()
	// Sanitize filename to prevent path traversal attacks. path.Base only
	// recognises '/' as a separator, so normalise Windows-style '\' first.
	sanitizedFilename := path.Base(strings.ReplaceAll(header.Filename, "\\", "/"))
	if sanitizedFilename == "." || sanitizedFilename == "/" || sanitizedFilename == "" {
		http.Error(w, "Invalid filename", http.StatusBadRequest)
		return
	}
	// Replace the key with uploaded file path under uploads/
	newKey := fmt.Sprintf("uploads/%s/%s/%s", namespace, uploadUUID, sanitizedFilename)
	if validateErr := sutils.ValidateUploadedArtifactKey(namespace, newKey); validateErr != nil {
		a.serverInternalError(ctx, fmt.Errorf("generated artifact key failed self-validation: %w", validateErr), w)
		return

View on GitHub (pinned to 35bff19146)

Solutions

  1. Configure a default artifactRepository in the workflow-controller-configmap (e.g. an s3 block).
  2. Add a storage backend (s3/gcs/azure/oss) directly to the artifact in the WorkflowTemplate's arguments.artifacts.
  3. Set spec.artifactRepositoryRef on the WorkflowTemplate or create an artifact-repositories ConfigMap in the namespace.
  4. Check controller logs at debug level for the 'Failed to resolve artifact repository' message to see why the default could not be applied.

Example fix

// before
artifacts:
  - name: data
// after
artifacts:
  - name: data
    s3:
      bucket: my-bucket
      key: path/in/bucket
Defensive patterns

Strategy: validation

Validate before calling

# Ensure a default artifact repository or explicit location exists before upload
kubectl -n argo get cm workflow-controller-configmap -o yaml | grep -A3 artifactRepository
kubectl -n $NS get cm artifact-repositories 2>/dev/null || echo 'no namespace artifact-repositories ConfigMap'

Try / catch

if (!artifact.s3 && !artifact.gcs && !artifact.azure && !artifact.oss && !defaultRepoConfigured) {
  throw new Error(`artifact '${artifact.name}' needs a storage location or default artifact repository`);
}

Prevention

When it happens

Trigger: The artifact in spec.arguments.artifacts has no s3/gcs/azure/oss block; no artifactRepositoryRef on the template; no artifact-repositories ConfigMap in the namespace; workflow-controller-configmap has no default artifactRepository configured; ResolveArtifactLocation failed (logged at debug) so the fallback location was never applied.

Common situations: Fresh Argo installs without artifact storage configured in the controller configmap; users assuming artifact uploads work without any artifact repository; namespace-level artifact-repositories ConfigMap misnamed or missing; template copied from an example that uses raw/passthrough artifacts with no location.

Related errors


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