{"record":{"id":"c562c4215d4d1d23","repo":"argoproj/argo-workflows","slug":"unable-to-resolve-outputs-from-scope-w","errorCode":null,"errorMessage":"unable to resolve outputs from scope: %w","messagePattern":"unable to resolve outputs from scope: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/controller/operator.go","lineNumber":3497,"sourceCode":"\t\t\t\t// optional: fail terminally, mirroring simple-tag substitution semantics.\n\t\t\t\treturn nil, argoerrors.Errorf(argoerrors.CodeBadRequest, \"output parameter %q: %q is an absent optional (skipped/omitted node output with no default)\", param.Name, param.ValueFrom.Parameter)\n\t\t\t}\n\t\t\tparam.Value = wfv1.AnyStringPtr(val)\n\t\t\tparam.ValueFrom = nil\n\t\t\toutputs.Parameters = append(outputs.Parameters, param)\n\t\t}\n\t}\n\tif len(tmpl.Outputs.Artifacts) > 0 {\n\t\toutputs.Artifacts = make([]wfv1.Artifact, 0)\n\t\tfor _, art := range tmpl.Outputs.Artifacts {\n\t\t\tresolvedArt, err := scope.resolveArtifact(ctx, &art)\n\t\t\tif err != nil {\n\t\t\t\t// If the artifact was not found and is optional, don't mark an error\n\t\t\t\tif strings.Contains(err.Error(), \"Unable to resolve\") && art.Optional {\n\t\t\t\t\twoc.log.WithField(\"artifactName\", art.Name).Warn(ctx, \"Optional artifact was not found; it won't be available as an output\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"unable to resolve outputs from scope: %w\", err)\n\t\t\t}\n\t\t\tif resolvedArt == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tresolvedArt.Name = art.Name\n\t\t\toutputs.Artifacts = append(outputs.Artifacts, *resolvedArt)\n\t\t}\n\t}\n\treturn &outputs, nil\n}\n\nfunc generateOutputResultRegex(name string, parentTmpl *wfv1.Template) (string, string) {\n\treferenceRegex := fmt.Sprintf(`\\.%s\\.outputs\\.result`, name)\n\texpressionRegex := fmt.Sprintf(`\\[['\\\"]%s['\\\"]\\]\\.outputs.result`, name)\n\tif parentTmpl.DAG != nil {\n\t\treferenceRegex = \"tasks\" + referenceRegex\n\t\texpressionRegex = \"tasks\" + expressionRegex\n\t} else if parentTmpl.Steps != nil {","sourceCodeStart":3479,"sourceCodeEnd":3515,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/controller/operator.go#L3479-L3515","documentation":"After resolving output parameters, the controller resolves each of the template's output artifacts from the scope (workflow/controller/operator.go:3497). If artifact resolution fails for reasons other than the handled 'not found + optional' case, the error is wrapped with 'unable to resolve outputs from scope: %w' and template execution fails. The wrapped inner error (e.g. 'Unable to resolve: {{...}} expression' or an invalid artifact path) is the real cause.","triggerScenarios":"An output artifact references something absent from the scope: `from:` pointing at a step/task/artifact name that doesn't exist or is misspelled; `subPath:` on an artifact whose subdirectory doesn't exist; a `fromExpression:` that evaluates to nothing; non-optional artifact whose source didn't produce the file.","commonSituations":"Typos in `from: '{{steps.x.outputs.artifacts.y}}'` references; a task failed/skipped earlier so its artifact never existed; marking an artifact optional doesn't help when the error is something other than 'Unable to resolve' (e.g. malformed expression); container didn't write the declared output path.","solutions":["Read the wrapped cause after '%w' — fix the referenced artifact/step name so it exists in scope (names are case-sensitive)","Mark the artifact `optional: true` only when a missing artifact is acceptable — note the lenient path requires the error to contain 'Unable to resolve'","Verify the upstream step actually succeeded and produced the artifact (check node status and pod logs)","For subPath outputs, confirm the subdirectory exists at runtime or add a fallback in the container script","Use `argo lint` and check DAG/task naming to catch broken references before submission"],"exampleFix":"# before\noutputs:\n  artifacts:\n  - name: model\n    from: '{{steps.train.outputs.artifacts.modle}}'   # typo\n# after\noutputs:\n  artifacts:\n  - name: model\n    from: '{{steps.train.outputs.artifacts.model}}'","handlingStrategy":"validation","validationCode":"# verify every artifact reference resolves to an existing step/task name\n# argo lint workflow.yaml\n# and mark artifacts that may legitimately be absent:\n# outputs:\n#   artifacts:\n#   - name: report\n#     optional: true\n#     from: '{{steps.gen.outputs.artifacts.report}}'","typeGuard":"func artifactRefExists(ref string, scope map[string]any) bool {\n    _, ok := scope[strings.Trim(ref, \"{}\")]\n    return ok\n}","tryCatchPattern":"null","preventionTips":["Spell-check `from:` references against actual step/task and artifact names (case-sensitive)","Use `optional: true` for artifacts that may not be produced","Check upstream nodes succeeded before relying on their artifacts","Ensure the container actually writes files to declared output paths","Run `argo lint` in CI for every workflow manifest"],"tags":["argo-workflows","output-artifacts","scope-resolution","template-references"],"backgroundTag":"artifact-resolution-failed","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}