argoproj/argo-workflows · error

error appending filename %s to key of artifact %+v: err: %w

Error message

error appending filename %s to key of artifact %+v: err: %w

What it means

When serving an artifact file the server can append a requested file name to the artifact's storage key (e.g. for log files or sub-paths). art.AppendToKey calls ArtifactLocation.GetKey(); if the artifact/location has no key or an unsupported/invalid location type, GetKey errors and the server wraps it as 'error appending filename <name> to key of artifact ...'. It means the artifact's resolved location has no usable key path to append to.

Source

Thrown at server/artifacts/artifact_server.go:729

		archiveLocation = template.ArchiveLocation // this is case 4
	}

	if templateName == "" || !archiveLocation.HasLocation() {
		ar, arErr := a.artifactRepositories.Get(ctx, wf.Status.ArtifactRepositoryRef) // this should handle cases 2, 3 and 5
		if arErr != nil {
			return art, nil, arErr
		}
		archiveLocation = ar.ToArtifactLocation()
	}

	err = art.Relocate(archiveLocation) // if the Artifact defines the location (case 1), it will be used; otherwise whatever archiveLocation is set to
	if err != nil {
		return art, nil, err
	}
	if fileName != nil {
		err = art.AppendToKey(*fileName)
		if err != nil {
			return art, nil, fmt.Errorf("error appending filename %s to key of artifact %+v: err: %w", *fileName, art, err)
		}
		logger.WithFields(logging.Fields{
			"fileName": *fileName,
			"artifact": art,
		}).Debug(ctx, "appended key to artifact")
	}

	driver, err := a.artDriverFactory(ctx, art, resources{kubeClient, wf.Namespace})
	if err != nil {
		return art, nil, err
	}
	logger.WithFields(logging.Fields{
		"artifact": art,
	}).Debug(ctx, "successfully located driver associated with artifact")

	return art, driver, nil
}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check the node's outputs: `argo get <wf> -o json | jq '.status.nodes["<nodeID>"].outputs'` — confirm the artifact exists and has a non-empty s3.key (or equivalent).
  2. Only request fileName/log downloads for completed nodes whose artifacts were actually produced; for pod logs use `argo logs <pod>` on a successful step.
  3. Fix the artifact repository configmap (workflow-controller-configmap artifactRepository s3.key format) if keys are being generated empty.
  4. Verify the workflow step succeeded — failed steps often have no artifact key; retry the step first.
  5. Inspect the artifact spec in your template: ensure the output artifact has a path and the location type supports keys (s3/gcs/azure/oss), not raw/inline.

Example fix

// before: requesting artifact file sub-path from a possibly-keyless artifact
f, err := svc.GetArtifactFile(ctx, nodeID, artName, isInput, &fileName) // panics on empty key
// after: verify the artifact has a key first
wf, _ := wfClient.ArgoprojV1alpha1().Workflows(ns).Get(ctx, wfName, metav1.GetOptions{})
node := wf.Status.Nodes[nodeID]
art := node.Outputs.GetArtifactByName(artName)
if art == nil || !art.HasLocation() {
    return fmt.Errorf("artifact %s on node %s has no stored location; step may have failed", artName, nodeID)
}
f, err := svc.GetArtifactFile(ctx, nodeID, artName, isInput, &fileName)
Defensive patterns

Strategy: validation

Validate before calling

node, ok := wf.Status.Nodes[nodeID]
if !ok || node.Phase != wfv1.NodeSucceeded {
    return fmt.Errorf("node %s not succeeded; artifact key may not exist", nodeID)
}
art := node.Outputs.GetArtifactByName(artifactName)
if art == nil || !art.HasLocation() {
    return fmt.Errorf("artifact %q has no stored location/key", artifactName)
}

Type guard

func artifactHasKey(node wfv1.NodeStatus, name string, isInput bool) bool {
    var art *wfv1.Artifact
    if isInput { art = node.Inputs.GetArtifactByName(name) } else { art = node.Outputs.GetArtifactByName(name) }
    return art != nil && art.HasLocation()
}

Try / catch

f, err := svc.GetArtifactFile(ctx, nodeID, artName, isInput, &fileName)
if err != nil {
    var appendErr string = "error appending filename"
    if strings.Contains(err.Error(), appendErr) {
        return fmt.Errorf("artifact has no key (step may not have run/completed): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetArtifactFile with a fileName (log download, `argo logs --artifact`, artifact sub-path request) for an artifact whose resolved ArtifactLocation has no key: e.g. artifact location is an empty/non-existent output, location key is unset because the step failed before producing the artifact, or the location type doesn't support GetKey (e.g. raw/inline or an artifact that only got a default repo with no key).

Common situations: Downloading logs of a failed/pending pod that never wrote its log artifact; requesting a sub-file from an artifact whose storage backend was misconfigured (empty key in artifact repository configmap); artifacts relocated from an archive location where the key portion is missing; using s3/git drivers with a key-less artifact spec.

Related errors


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