argoproj/argo-workflows · error
workflow cannot be nil
Error message
workflow cannot be nil
What it means
ApplySubmitOpts mutates a *wfv1.Workflow with CLI/server submit options; it requires a non-nil workflow pointer. A nil wf is a programming error by the caller (the workflow was never formulated/loaded), so it fails fast with this error rather than panicking.
Source
Thrown at workflow/util/util.go:249
func PopulateSubmitOpts(command *cobra.Command, submitOpts *wfv1.SubmitOpts, parameterFile *string, includeDryRun bool) {
command.Flags().StringVar(&submitOpts.Name, "name", "", "override metadata.name")
command.Flags().StringVar(&submitOpts.GenerateName, "generate-name", "", "override metadata.generateName")
command.Flags().StringVar(&submitOpts.Entrypoint, "entrypoint", "", "override entrypoint")
command.Flags().StringArrayVarP(&submitOpts.Parameters, "parameter", "p", []string{}, "pass an input parameter")
command.Flags().StringVar(&submitOpts.ServiceAccount, "serviceaccount", "", "run all pods in the workflow using specified serviceaccount")
command.Flags().StringVarP(parameterFile, "parameter-file", "f", "", "pass a file containing all input parameters")
command.Flags().StringVarP(&submitOpts.Labels, "labels", "l", "", "Comma separated labels to apply to the workflow. Will override previous values.")
if includeDryRun {
command.Flags().BoolVar(&submitOpts.DryRun, "dry-run", false, "modify the workflow on the client-side without creating it")
command.Flags().BoolVar(&submitOpts.ServerDryRun, "server-dry-run", false, "send request to server with dry-run flag which will modify the workflow without creating it")
}
}
// ApplySubmitOpts applies the submit options to a workflow object.
func ApplySubmitOpts(wf *wfv1.Workflow, opts *wfv1.SubmitOpts) error {
if wf == nil {
return fmt.Errorf("workflow cannot be nil")
}
if opts == nil {
opts = &wfv1.SubmitOpts{}
}
if opts.Entrypoint != "" {
wf.Spec.Entrypoint = opts.Entrypoint
}
if opts.ServiceAccount != "" {
wf.Spec.ServiceAccountName = opts.ServiceAccount
}
if opts.PodPriorityClassName != "" {
wf.Spec.PodPriorityClassName = opts.PodPriorityClassName
}
if opts.Priority != nil {
wf.Spec.Priority = opts.Priority
}
View on GitHub (pinned to 35bff19146)
Solutions
- Ensure the workflow is successfully created/parsed before calling ApplySubmitOpts and propagate earlier errors
- Add a nil check on the result of the formulate/parse step before applying submit options
- If using CLI, verify the file/URL/- arguments actually produce a workflow (argo submit with valid input)
Example fix
// before
wf, err := util.FromFile(...) // err ignored
_ = util.ApplySubmitOpts(wf, opts) // wf is nil
// after
wf, err := util.FromFile(...)
if err != nil { return err }
if err := util.ApplySubmitOpts(wf, opts); err != nil { return err } Defensive patterns
Strategy: type-guard
Validate before calling
if wf == nil {
return fmt.Errorf("cannot submit: workflow is nil, check formulate/parse step")
} Type guard
func workflowReady(wf *wfv1.Workflow) bool {
return wf != nil && wf.Spec.Entrypoint != ""
} Try / catch
if err := util.ApplySubmitOpts(wf, opts); err != nil {
if strings.Contains(err.Error(), "workflow cannot be nil") {
return fmt.Errorf("bug: workflow not constructed before ApplySubmitOpts: %w", err)
}
return err
} Prevention
- Always check errors from workflow formulation before applying submit opts
- Wrap submit pipelines so nil workflows cannot reach ApplySubmitOpts
- Add unit tests covering the full formulate -> ApplySubmitOpts path
When it happens
Trigger: Calling ApplySubmitOpts(nil, opts) directly, or passing a workflow that a prior formulate/parse step failed to produce (caller ignored an earlier error and passed a nil *wfv1.Workflow) from CreateCronWorkflows, updateCronWorkflows, submitWorkflows, or SubmitWorkflow.
Common situations: Custom tooling built on workflow/util that skips workflow formulation; error from unmarshal/FromFile ignored so wf stays nil; refactoring that reordered code so ApplySubmitOpts runs before the wf is created.
Related errors
- cron schedules must consist of 5 values only
- ${e.Usage()}
- --completed and --running cannot be used together
- cannot combine --from with file arguments
- cannot watch more than one workflow
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/34c0d9feb9b03144.
Report an issue: GitHub.