argoproj/argo-workflows · error

failed to convert result to JSON "%s" expression: %w

Error message

failed to convert result to JSON "%s" expression: %w

What it means

This error occurs in the Argo Workflows event dispatch (EventBinding -> Workflow submission) path when the result of evaluating a `valueFrom.event` expr-lang expression for an event-binding parameter cannot be serialized with json.Marshal. Argo stores each evaluated parameter as a JSON-encoded value in the created Workflow's arguments, so any expr value containing types JSON cannot represent (channels, funcs, NaN/Inf floats, unsupported maps) aborts the dispatch. The wrapped %w contains the exact json.MarshalUnsupportedTypeError.

Source

Thrown at server/event/dispatch/operation.go:159

		//nolint: contextcheck
		creator.LabelCreator(o.ctx, wf)
		labels.Label(wf, common.LabelKeyWorkflowEventBinding, wfeb.Name)
		if submit.Arguments != nil {
			for _, p := range submit.Arguments.Parameters {
				if p.ValueFrom == nil {
					return nil, fmt.Errorf("malformed workflow template parameter \"%s\": valueFrom is nil", p.Name)
				}
				program, compileErr := expr.Compile(p.ValueFrom.Event, expr.Env(o.env))
				if compileErr != nil {
					return nil, fmt.Errorf("failed to compile workflow template parameter %s expression: %w", p.Name, compileErr)
				}
				result, runErr := expr.Run(program, o.env)
				if runErr != nil {
					return nil, fmt.Errorf("failed to evaluate workflow template parameter \"%s\" expression: %w", p.Name, runErr)
				}
				data, marshalErr := json.Marshal(result)
				if marshalErr != nil {
					return nil, fmt.Errorf("failed to convert result to JSON \"%s\" expression: %w", p.Name, marshalErr)
				}
				wf.Spec.Arguments.Parameters = append(wf.Spec.Arguments.Parameters, wfv1.Parameter{Name: p.Name, Value: wfv1.AnyStringPtr(wfv1.Item{Value: data})})
			}
		}
		wf, err = client.ArgoprojV1alpha1().Workflows(wfeb.Namespace).Create(ctx, wf, metav1.CreateOptions{})
		if err != nil {
			return nil, fmt.Errorf("failed to create workflow: %w", err)
		}
		return wf, nil
	}
	return nil, nil
}

func (o *Operation) populateWorkflowMetadata(wf *wfv1.Workflow, metadata *metav1.ObjectMeta) error {
	if len(metadata.Name) > 0 {
		evalName, err := o.evaluateStringExpression(metadata.Name, "name")
		if err != nil {
			return err

View on GitHub (pinned to 35bff19146)

Solutions

  1. Fix the valueFrom.event expression in the EventBinding/WorkflowTemplate so it returns a JSON-safe value, e.g. coerce with string(...) or sprig funcs instead of raw arithmetic that can produce NaN/Inf
  2. Inspect the wrapped json.Marshal error (%w) to identify the offending field/type, then sanitize that field in the event payload before dispatch
  3. If a custom expr function is at fault, change it to return only JSON-serializable types (string, number, bool, []any, map[string]any)
  4. Validate the expression result with a pre-check in test: compile and run it with a sample payload and json.Marshal the result before deploying the binding

Example fix

// before (EventBinding parameter expression can yield +Inf)
valueFrom:
  event: payload.data.a / payload.data.b
// after
valueFrom:
  event: string(payload.data.a / payload.data.b) # or guard: payload.data.b == 0 ? "0" : string(payload.data.a / payload.data.b)
Defensive patterns

Strategy: validation

Validate before calling

// Test the binding expression offline before deploying
data, err := json.Marshal(exprResult)
if err != nil {
    return fmt.Errorf("binding expression result not JSON-serializable: %w", err)
}

Prevention

When it happens

Trigger: Dispatching an event via an EventBinding whose WorkflowTemplate reference declares an arguments parameter with valueFrom.event whose expr evaluation returns a value json.Marshal rejects — e.g. expr built-ins returning func values, NaN/Inf from arithmetic like `payload.x / 0` on floats, cyclic/odd-typed data embedded in the event payload, or a custom expr function registered in exprenv that returns a non-serializable Go type.

Common situations: Users write event expressions doing float division that yields +Inf/NaN; a sensor payload carries deeply unusual data that jsonutil.Jsonify did not normalize; a custom expr function (GetFuncMap extension) returns a Go func/channel; upgrading Argo changes the expr runtime so an expression that previously returned a string now returns a non-string type.

Related errors


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