argoproj/argo-workflows · error

json: unknown field "%s"

Error message

json: unknown field "%s"

What it means

ParallelSteps (the anonymous list inside a template's `steps`) uses a custom UnmarshalJSON because WorkflowStep is serialized as a bare JSON list. Since the standard strict-decoding unknown-field enforcement does not apply to this custom unmarshaller, it manually checks each key against the fields of WorkflowStep and returns this error for any unrecognized key.

Source

Thrown at pkg/apis/workflow/v1alpha1/workflow_types.go:678

	var candidate []map[string]any
	err := json.Unmarshal(value, &candidate)
	if err != nil {
		return err
	}

	// Generate a list of all the available JSON fields of the WorkflowStep struct
	availableFields := map[string]bool{}
	reflectType := reflect.TypeFor[WorkflowStep]()
	for field := range reflectType.Fields() {
		cleanString := strings.ReplaceAll(field.Tag.Get("json"), ",omitempty", "")
		availableFields[cleanString] = true
	}

	// Enforce that no unknown fields are present
	for _, step := range candidate {
		for key := range step {
			if _, ok := availableFields[key]; !ok {
				return fmt.Errorf(`json: unknown field "%s"`, key)
			}
		}
	}

	// Finally, attempt to fully unmarshal the struct
	err = json.Unmarshal(value, &p.Steps)
	if err != nil {
		return err
	}
	return nil
}

func (p ParallelSteps) MarshalJSON() ([]byte, error) {
	return json.Marshal(p.Steps)
}

func (p ParallelSteps) OpenAPISchemaType() []string {
	return []string{"array"}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Fix the reported field name to a valid WorkflowStep field (name, template, templateRef, inline, arguments, when, onExit, continueOn, hooks, withItems, withParam, withSequence, etc.)
  2. Check the CRD schema version you are running against; remove fields not present in it
  3. Run `argo lint` locally to catch typos before applying

Example fix

// before
- nam: build
  templete: build-template
// after
- name: build
  template: build-template
Defensive patterns

Strategy: validation

Validate before calling

var candidate []map[string]any
if err := json.Unmarshal(stepBytes, &candidate); err != nil {
    return err
}
allowed := map[string]bool{"name":true,"template":true,"templateRef":true,"inline":true,"arguments":true,"when":true,"onExit":true,"continueOn":true,"hooks":true,"withItems":true,"withParam":true,"withSequence":true}
for _, step := range candidate {
    for k := range step {
        if !allowed[k] {
            return fmt.Errorf(`unknown field %q in steps`, k)
        }
    }
}

Try / catch

err := json.Unmarshal(data, &wf)
if err != nil {
    var unknown [1]string
    if n, _ := fmt.Sscanf(err.Error(), `json: unknown field %q`, &unknown[0]); n == 1 {
        return fmt.Errorf("typo in steps field: %s", unknown[0])
    }
    return err
}

Prevention

When it happens

Trigger: Unmarshalling a Workflow (via kubectl apply, argo submit, or the k8s API) where a step object inside `steps` contains a JSON key that is not a WorkflowStep field, e.g. a typo like `templete` or `nam`.

Common situations: Typo in a step field name; using a field from an older/newer spec version that no longer exists; copy-pasting from documentation of a different CRD version.

Related errors


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