argoproj/argo-workflows · error
artifact key %q must have a valid UUID segment: %w
Error message
artifact key %q must have a valid UUID segment: %w
What it means
ValidateUploadedArtifactKey validates that a client-supplied artifact key exactly matches the upload-endpoint format uploads/{namespace}/{uuid}/{filename}. The third segment must parse as a UUID (github.com/google/uuid.Parse). This check exists because the key is applied to the artifact location without further verification, so malformed segments could otherwise enable path manipulation or key confusion.
Source
Thrown at server/utils/artifactkey.go:45
}
if strings.HasPrefix(key, "/") {
return fmt.Errorf("artifact key %q must not be an absolute path", key)
}
if path.Clean(key) != key {
return fmt.Errorf("artifact key %q is not in canonical form", key)
}
parts := strings.Split(key, "/")
if len(parts) != 4 {
return fmt.Errorf("artifact key %q must have exactly 4 segments: uploads/{namespace}/{uuid}/{filename}", key)
}
if slices.Contains(parts, "") {
return fmt.Errorf("artifact key %q must not contain empty segments", key)
}
uuidSegment := parts[2]
if _, err := uuid.Parse(uuidSegment); err != nil {
return fmt.Errorf("artifact key %q must have a valid UUID segment: %w", key, err)
}
filename := parts[3]
if path.Base(filename) != filename {
return fmt.Errorf("artifact key %q must have a bare filename segment", key)
}
return nil
}
View on GitHub (pinned to 35bff19146)
Solutions
- Use the exact key string returned by the artifact upload endpoint rather than constructing it by hand.
- Verify the key has exactly 4 segments and that segment index 2 is a valid UUID: run uuid.Parse on it client-side before sending.
- If you have only the filename, re-request a fresh upload slot from the server so a correct UUID is generated.
Example fix
// before
key := "uploads/myns/step-1-output/results.tgz"
// after
key := fmt.Sprintf("uploads/%s/%s/%s", namespace, uuid.NewString(), "results.tgz") Defensive patterns
Strategy: validation
Validate before calling
func looksLikeUploadKey(namespace, key string) bool {
parts := strings.Split(key, "/")
return len(parts) == 4 && parts[0] == "uploads" && parts[1] == namespace &&
func() bool { _, err := uuid.Parse(parts[2]); return err == nil }()
} Type guard
func isValidUUID(s string) bool { _, err := uuid.Parse(s); return err == nil } Try / catch
if err := utils.ValidateUploadedArtifactKey(ns, key); err != nil {
var uerr *uuid.Error
if errors.As(err, &uerr) {
return fmt.Errorf("regenerate upload key: UUID segment invalid: %w", err)
}
return err
} Prevention
- Always take the key verbatim from the upload endpoint response, never assemble it manually.
- Keep a client-side helper that formats keys as uploads/{ns}/{uuid}/{filename} so the format lives in one place.
- Validate keys with uuid.Parse before any upload/download call.
When it happens
Trigger: Calling ValidateUploadedArtifactKey with a key whose 3rd '/'-separated segment (parts[2]) is not a parseable UUID — e.g. 'uploads/myns/not-a-uuid/file.txt', 'uploads/myns/12345/file.txt', or 'uploads/myns//file.txt' shaped so the uuid slot holds arbitrary text.
Common situations: Hand-constructing artifact keys instead of using the ones the upload endpoint generated; copying a key and truncating/altering the UUID; tools that build keys from workflow/step names instead of the server-generated UUID; version drift where older clients produced keys without the UUID segment.
Related errors
- artifact key %q must have a bare filename segment
- %w
- successCondition, failureCondition and outputs are not suppo
- failed to load non-plugin input artifacts: %w
- failed to load input artifacts from plugin %q: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/e6530b465379c150.
Report an issue: GitHub.