argoproj/argo-workflows · error
invalid cache key: %s
Error message
invalid cache key: %s
What it means
When saving a memoization cache entry, the cache key must match cacheKeyRegex (a DNS-subdomain-like pattern). Keys that are too long (>253 chars) or contain invalid characters are rejected with this error, because ConfigMap keys/annotations cannot safely hold arbitrary strings.
Source
Thrown at workflow/controller/cache/configmap_cache.go:154
err := retry.OnError(kwait.Backoff{
Duration: time.Second,
Factor: 2,
Jitter: 0.1,
Steps: 5,
Cap: 30 * time.Second,
}, func(err error) bool {
return argoerr.IsTransientErr(ctx, err) || apierr.IsConflict(err)
}, func() error {
innerErr := c.save(ctx, key, nodeID, value)
return innerErr
})
return err
}
func (c *configMapCache) save(ctx context.Context, key string, nodeID string, value *wfv1.Outputs) error {
if !cacheKeyRegex.MatchString(key) {
errString := fmt.Sprintf("invalid cache key: %s", key)
err := errors.New(errString)
c.logError(ctx, err, logging.Fields{"key": key}, errString)
return err
}
c.lock.Lock()
defer c.lock.Unlock()
c.logInfo(ctx, logging.Fields{"key": key, "nodeID": nodeID}, "Saving ConfigMap cache entry")
cache, err := c.kubeClient.CoreV1().ConfigMaps(c.namespace).Get(ctx, c.name, metav1.GetOptions{})
if apierr.IsNotFound(err) || cache == nil {
cache, err = c.kubeClient.CoreV1().ConfigMaps(c.namespace).Create(ctx, &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: c.name,
},
}, metav1.CreateOptions{})
if err != nil {
c.logError(ctx, err, logging.Fields{"key": key, "nodeID": nodeID}, "Error saving to ConfigMap cache")View on GitHub (pinned to 35bff19146)
Solutions
- Shorten the memoization key to <=253 chars and keep it to [a-z0-9] with '-'/'.' separators.
- Hash a long value into the key instead of embedding it, e.g. use sha256 of the input string.
- Check the template expression building the key for unexpected content (full URLs, paths).
Example fix
# before
memoization:
key: config-{{workflow.parameters.configUrl}}
# after
memoization:
key: config-{{=sprig.sha256sum(workflow.parameters.configUrl)}} Defensive patterns
Strategy: validation
Validate before calling
import "regexp"
var cacheKeyRegex = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`)
func validCacheKey(k string) bool {
return len(k) <= 253 && cacheKeyRegex.MatchString(k)
} Type guard
func isValidCacheKey(key string) bool {
return len(key) <= 253 && regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`).MatchString(key)
} Try / catch
if err := node.SaveOutput(...); err != nil && strings.Contains(err.Error(), "invalid cache key") {
// recompute a shorter, DNS-safe key and retry
} Prevention
- Keep memoization keys short and DNS-subdomain-safe (<=253 chars, lowercase alnum/-/.)
- Hash long inputs (sha256) instead of embedding raw URLs/IDs in keys
- Avoid template expressions that may inject spaces, slashes, or uppercase into keys
When it happens
Trigger: Calling save() (via SaveStreamViaTempFile or the anonymous key-construction path) with a memoization `key` value that fails cacheKeyRegex — typically a key longer than 253 characters or containing illegal characters (spaces, slashes, uppercase-unsafe values, etc.).
Common situations: Users set `memoization.key` from template expressions that embed long IDs (image digests, URLs, git SHAs concatenated); keys with `/` or spaces; generated keys exceeding ConfigMap limits.
Related errors
- cron schedules must consist of 5 values only
- ${e.Usage()}
- --completed and --running cannot be used together
- memoization configmap doesn't have %s label, refusing to use
- CodeBadRequest
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/2240e574448c5cd1.
Report an issue: GitHub.