argoproj/argo-workflows · error

malformed cache entry: could not unmarshal JSON; unable to p

Error message

malformed cache entry: could not unmarshal JSON; unable to parse: %w

What it means

When loading a memoization entry from a ConfigMap, the stored JSON string is unmarshalled into cache.Entry. If the ConfigMap data value is not valid JSON or does not match the Entry schema, the load fails with this wrapped parse error so the controller does not silently treat corrupted data as a cache hit.

Source

Thrown at workflow/controller/cache/configmap_cache.go:117

		return nil, err
	}
	err = c.validateConfigmap(ctx, cm)
	if err != nil {
		return nil, err
	}

	c.logInfo(ctx, logging.Fields{}, "config map cache loaded")
	hitTime := time.Now()
	rawEntry, ok := cm.Data[key]
	if !ok || rawEntry == "" {
		c.logInfo(ctx, logging.Fields{}, "config map cache miss: entry does not exist")
		return nil, nil
	}

	var entry Entry
	err = json.Unmarshal([]byte(rawEntry), &entry)
	if err != nil {
		return nil, fmt.Errorf("malformed cache entry: could not unmarshal JSON; unable to parse: %w", err)
	}

	entry.LastHitTimestamp = metav1.Time{Time: hitTime}
	entryJSON, err := json.Marshal(entry)
	if err != nil {
		c.logError(ctx, err, logging.Fields{"key": key}, "Unable to marshal cache entry with last hit timestamp")
		return nil, fmt.Errorf("unable to marshal cache entry with last hit timestamp: %w", err)
	}
	cm.Data[key] = string(entryJSON)

	_, err = c.kubeClient.CoreV1().ConfigMaps(c.namespace).Update(ctx, cm, metav1.UpdateOptions{})
	if err != nil {
		return nil, err
	}
	return &entry, nil
}

func (c *configMapCache) Save(ctx context.Context, key string, nodeID string, value *wfv1.Outputs) error {

View on GitHub (pinned to 35bff19146)

Solutions

  1. kubectl get cm <cache-cm> -o jsonpath='{.data.<key>}' and validate the value parses as JSON with the Entry fields (ExitCode, NodeID, CreationTimestamp, LastHitTimestamp).
  2. Delete the corrupted key from the ConfigMap so the memoized node re-executes and re-saves a fresh entry.
  3. If all entries are stale-schema, delete the whole ConfigMap (memoization entries are safe to rebuild).
  4. Verify no external tooling writes to memoization ConfigMaps (label selector: workflows.argoproj.io/workflow).
  5. Pin/upgrade the Argo version consistently so schema matches entries on disk.

Example fix

// before: manually written entry
cm.Data["key"] = "done"
// after: valid JSON entry
import encjson "encoding/json"
b, _ := encjson.Marshal(controllercache.Entry{NodeID: "abc", ExitCode: "0", CreationTimestamp: metav1.Now(), LastHitTimestamp: metav1.Now()})
cm.Data["key"] = string(b)
Defensive patterns

Strategy: validation

Validate before calling

const raw = cm.data?.[key];
try { const e = JSON.parse(raw); if (!('nodeID' in e) && !('exitCode' in e)) throw new Error('not an Entry'); } catch { console.warn(`corrupt cache entry for key ${key}; delete it before lookup`); }

Type guard

function isCacheEntry(raw) {
  if (typeof raw !== 'string') return false;
  try { const e = JSON.parse(raw); return e && typeof e === 'object' && 'nodeID' in e; } catch { return false; }
}

Try / catch

try {
  entry, err := cache.Load(ctx, key)
  if err != nil {
    var parseErr *json.SyntaxError
    if errors.As(err, &parseErr) || strings.Contains(err.Error(), "could not unmarshal JSON") {
      // treat as cache miss: delete corrupt key, let node re-execute
    } else { return err }
  }
}

Prevention

When it happens

Trigger: cm.Data[key] was written by hand or by another tool with non-JSON content; entry JSON was truncated (ConfigMap size edits, manual kubectl edit); the Entry struct changed between Argo versions so old entries no longer unmarshal.

Common situations: Manually editing the memoization ConfigMap; migrating from an older Argo version with a different entry schema; another controller or script sharing the same ConfigMap and writing raw strings; truncated entries after ConfigMap size limits.

Understand the failure class

Related errors


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