argoproj/argo-workflows · error
cannot finish template replacement because the result was in
Error message
cannot finish template replacement because the result was invalid JSON
What it means
After tag substitution succeeded, the result string failed a final json.Valid check in Replace — a replaced value injected content (e.g. unescaped quotes or braces) that broke the JSON structure that was valid going in.
Source
Thrown at util/template/replace.go:56
// entry marks an absent optional (a skipped/omitted node's output with no default), and a simple
// tag resolving to nil is a terminal error regardless of allowUnresolved, which only governs tags
// whose key is missing entirely.
func Replace(ctx context.Context, s string, replaceMap map[string]any, allowUnresolved bool) (string, error) {
if !json.Valid([]byte(s)) {
return "", errors.New("cannot do template replacements with invalid JSON")
}
t, err := NewTemplate(s)
if err != nil {
return "", err
}
replacedString, err := t.Replace(ctx, replaceMap, allowUnresolved)
if err != nil {
return s, err
}
if !json.Valid([]byte(replacedString)) {
return s, errors.New("cannot finish template replacement because the result was invalid JSON")
}
return replacedString, nil
}
// ReplaceStrictAny behaves like Replace but enforces that tags starting with any of strictPrefixes
// MUST be resolved, even if allowUnresolved behavior is otherwise active (implicit). It takes raw
// values, preserving nil entries so that expression tags can distinguish an absent (nil) value from
// an empty string (e.g. via `??`). A simple tag resolving to a nil value is a terminal error (not a
// missing-variable error): an absent optional must be handled by a producer default, a consumer
// input default (dropping the argument before substitution), or an expression fallback.
func ReplaceStrictAny(ctx context.Context, s string, replaceMap map[string]any, strictPrefixes []string) (string, error) {
if !json.Valid([]byte(s)) {
return "", errors.New("cannot do template replacements with invalid JSON")
}
t, err := NewTemplate(s)
if err != nil {View on GitHub (pinned to 35bff19146)
Solutions
- JSON-escape or properly quote the substituted parameter values
- Check parameter values for raw quotes/newlines injected into JSON fields
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at util/template/replace.go:56 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/3c7becc71943fbbf.
Report an issue: GitHub.