{"record":{"id":"6a700d0ba412aa1b","repo":"argoproj/argo-workflows","slug":"codebadrequest","errorCode":"CodeBadRequest","errorMessage":"failed to marshal artifact subpath for templating","messagePattern":"failed to marshal artifact subpath for templating","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/controller/scope.go","lineNumber":236,"sourceCode":"\t\treturn nil, err\n\t}\n\tvalArt, ok := val.(wfv1.Artifact)\n\tif !ok {\n\t\t// If the workflow refers itself input artifacts in fromExpression, the val type is \"*wfv1.Artifact\"\n\t\tptArt, ok := val.(*wfv1.Artifact)\n\t\tif !ok {\n\t\t\treturn nil, errors.Errorf(errors.CodeBadRequest, \"Variable {{%v}} is not an artifact\", art)\n\t\t}\n\t\tvalArt = *ptArt\n\t}\n\n\tif art.SubPath != \"\" {\n\t\t// Copy resolved artifact pointer before adding subpath\n\t\tcopyArt := valArt.DeepCopy()\n\n\t\tsubPathAsJSON, err := json.Marshal(art.SubPath)\n\t\tif err != nil {\n\t\t\treturn copyArt, errors.New(errors.CodeBadRequest, \"failed to marshal artifact subpath for templating\")\n\t\t}\n\n\t\tresolvedSubPathAsJSON, err := template.Replace(ctx, string(subPathAsJSON), s.getParametersAny(nil), true)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tvar resolvedSubPath string\n\t\terr = json.Unmarshal([]byte(resolvedSubPathAsJSON), &resolvedSubPath)\n\t\tif err != nil {\n\t\t\treturn copyArt, errors.New(errors.CodeBadRequest, \"failed to unmarshal artifact subpath for templating\")\n\t\t}\n\n\t\terr = copyArt.AppendToKey(resolvedSubPath)\n\t\tif err != nil && copyArt.Optional { // Ignore error when artifact optional\n\t\t\treturn copyArt, nil\n\t\t}\n\t\treturn copyArt, err","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/controller/scope.go#L218-L254","documentation":"When resolving an artifact with a `subPath` expression, the controller marshals the raw SubPath string to JSON so it can be template-rendered. A json.Marshal failure here is effectively impossible for plain strings, but if it happens the controller returns this CodeBadRequest error instead of proceeding with a corrupted value.","triggerScenarios":"Calling resolveArtifact on an artifact whose SubPath is set and json.Marshal(art.SubPath) returns an error (e.g. unexpected/invalid value passed through the API or a custom artifact source).","commonSituations":"Practically rare; seen when artifact specs are built programmatically or via SDKs with unusual values, or when a controller/plugin feeds malformed artifact data into scope resolution.","solutions":["Inspect the artifact spec producing the failure (kubectl get wf <name> -o yaml) and ensure `subPath` is a plain string.","Rebuild/resubmit the workflow with a corrected artifact definition.","If building artifacts via SDK, ensure subPath is passed as a string, not another JSON type."],"exampleFix":"// before (SDK-built artifact)\nart.SubPath = 42\n// after\nart.SubPath = \"data/output.txt\"","handlingStrategy":"validation","validationCode":"if art.SubPath != \"\" {\n    if _, err := json.Marshal(art.SubPath); err != nil {\n        return fmt.Errorf(\"artifact subPath %q is not a valid string value\", art.SubPath)\n    }\n}","typeGuard":null,"tryCatchPattern":"resolved, err := scope.ResolveArtifact(ctx, art)\nif err != nil && strings.Contains(err.Error(), \"failed to marshal artifact subpath\") {\n    // inspect artifact spec in the Workflow YAML and fix subPath\n}","preventionTips":["Ensure subPath is always a plain string when building artifacts via SDKs","Validate artifact specs with argo lint before submission","Avoid plugins/custom sources injecting non-string subPath values"],"tags":["template","artifact","subpath","bad-request"],"backgroundTag":"artifact-subpath-templating-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"}