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
- 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).
- Only request fileName/log downloads for completed nodes whose artifacts were actually produced; for pod logs use `argo logs <pod>` on a successful step.
- Fix the artifact repository configmap (workflow-controller-configmap artifactRepository s3.key format) if keys are being generated empty.
- Verify the workflow step succeeded — failed steps often have no artifact key; retry the step first.
- 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
- Only request artifact files/sub-paths for nodes in Succeeded phase.
- Ensure artifactRepository s3.key format in the controller configmap is correct so generated keys are never empty.
- For pod logs, use the log API rather than artifact files for non-completed steps.
- Prefer output artifacts with explicit paths in templates.
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
- unable to source artifact paths: %w
- failed to put file: %w
- unable to process data source: %w
- Failed to save artifact: %v
- Artifact driver connection validation failed: %v
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/9b145f8709dea8a7.
Report an issue: GitHub.