argoproj/argo-workflows · info
failed to marshal patch: %w
Error message
failed to marshal patch: %w
What it means
In archiveWorkflowAux (workflow/controller/controller.go:1417), after successfully archiving, the controller builds a JSON merge patch setting the workflows.argoproj.io/archiving-status label to Archived. This error means json.Marshal of that tiny static map failed — practically unreachable with the hardcoded map (json.Marshal only fails on unsupported types), so it indicates an exotic build/runtime anomaly rather than a user-fixable condition.
Source
Thrown at workflow/controller/controller.go:1417
err = wfc.hydrator.Hydrate(ctx, wf)
if err != nil {
return fmt.Errorf("failed to hydrate workflow: %w", err)
}
logger := logging.RequireLoggerFromContext(ctx)
logger.WithFields(logging.Fields{"namespace": wf.Namespace, "workflow": wf.Name, "uid": wf.UID}).Info(ctx, "archiving workflow")
err = wfc.wfArchive.ArchiveWorkflow(ctx, wf)
if err != nil {
return fmt.Errorf("failed to archive workflow: %w", err)
}
data, err := json.Marshal(map[string]any{
"metadata": metav1.ObjectMeta{
Labels: map[string]string{
common.LabelKeyWorkflowArchivingStatus: "Archived",
},
},
})
if err != nil {
return fmt.Errorf("failed to marshal patch: %w", err)
}
_, err = wfc.wfclientset.ArgoprojV1alpha1().Workflows(un.GetNamespace()).Patch(
ctx,
un.GetName(),
types.MergePatchType,
data,
metav1.PatchOptions{},
)
if err != nil {
// from this point on we have successfully archived the workflow, and it is possible for the workflow to have actually
// been deleted, so it's not a problem to get a `IsNotFound` error
if apierr.IsNotFound(err) {
return nil
}
return fmt.Errorf("failed to mark the workflow archived: %w", err)
}
return nil
}View on GitHub (pinned to 35bff19146)
Solutions
- If you forked and changed the patch payload, ensure all values are JSON-serializable (use string labels, plain maps).
- Rebuild the controller binary from unmodified upstream sources.
- If reproducible, capture the inner marshal error via the wrapped %w chain and file an issue.
Example fix
// before (forked payload with unsupported type)
data, err := json.Marshal(map[string]any{"metadata": metav1.ObjectMeta{Labels: map[string]string{...}, ManagedFields: someFunc}})
// after
un, _ := signaling.ObjectMapper.ObjectToUnstructured(...)
data, err := json.Marshal(map[string]any{"metadata": metav1.ObjectMeta{Labels: map[string]string{common.LabelKeyWorkflowArchivingStatus: "Archived"}}}) Defensive patterns
Strategy: try-catch
Try / catch
data, err := json.Marshal(map[string]any{
"metadata": metav1.ObjectMeta{Labels: map[string]string{common.LabelKeyWorkflowArchivingStatus: "Archived"}},
})
if err != nil {
return fmt.Errorf("failed to marshal patch: %w", err)
} Prevention
- Keep the patch payload limited to JSON-serializable values (string label maps)
- If forking, never embed funcs/channels/unserializable types in marshal targets
- This path is effectively unreachable with upstream code; investigate build integrity if hit
When it happens
Trigger: json.Marshal(map[string]any{"metadata": metav1.ObjectMeta{...}}) returns an error — with the fixed literal payload this should never happen; only conceivable via a corrupted standard library/runtime or if the literal was modified to include non-serializable values (channels/funcs) in a fork.
Common situations: Only in modified/forked code where the patch payload includes unsupported types; no real-world cluster configuration triggers it.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- failed to marshal container args for %s: %w
- invalid TTL
- error converting %s: %w
- failed to parse TypeMeta: %w
- failed to unmarshal container args: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/5583c7a71adec26a.
Report an issue: GitHub.