{"record":{"id":"7561e4601d5d1639","repo":"GoogleContainerTools/skaffold","slug":"custom-action-s-have-more-than-one-execution-mode","errorCode":null,"errorMessage":"custom action %s have more than one execution mode defined. custom actions must have only one execution mode","messagePattern":"custom action (.+?) have more than one execution mode defined\\. custom actions must have only one execution mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/schema/validation/validation.go","lineNumber":787,"sourceCode":"\n\tfor _, a := range acs {\n\t\tif len(a.Containers) == 0 {\n\t\t\terrs = append(errs, fmt.Errorf(\"custom action %s doesn't have containers. custom actions must have one or more containers associated\", a.Name))\n\t\t}\n\t}\n\treturn\n}\n\nfunc validateCustomActionsExecModes(runCtx *runcontext.RunContext) (errs []error) {\n\tacs := []latest.Action{}\n\n\tfor _, pipeline := range runCtx.GetPipelines() {\n\t\tacs = append(acs, pipeline.CustomActions...)\n\t}\n\n\tfor _, a := range acs {\n\t\tif a.ExecutionModeConfig.KubernetesClusterExecutionMode != nil && a.ExecutionModeConfig.LocalExecutionMode != nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"custom action %s have more than one execution mode defined. custom actions must have only one execution mode\", a.Name))\n\t\t}\n\t}\n\n\treturn\n}\n\n// validateCustomTest\n// - makes sure that command is not empty\n// - makes sure that dependencies.ignore is only used in conjunction with dependencies.paths\nfunc validateCustomTest(cfg *parser.SkaffoldConfigEntry, tcs []*latest.TestCase) (cfgErrs []ErrorWithLocation) {\n\tfor i, tc := range tcs {\n\t\tfor j, ct := range tc.CustomTests {\n\t\t\tif ct.Command == \"\" {\n\t\t\t\tcfgErrs = append(cfgErrs, ErrorWithLocation{\n\t\t\t\t\tError:    fmt.Errorf(\"custom test command must not be empty;\"),\n\t\t\t\t\tLocation: cfg.YAMLInfos.Locate(&cfg.Test[i].CustomTests[j]),\n\t\t\t\t})\n\t\t\t\treturn","sourceCodeStart":769,"sourceCodeEnd":805,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/schema/validation/validation.go#L769-L805","documentation":"A Skaffold custom action must specify exactly one execution mode: either Kubernetes cluster execution or local execution, not both. validateCustomActionsExecModes rejects actions where both `ExecutionModeConfig.KubernetesClusterExecutionMode` and `LocalExecutionMode` are set.","triggerScenarios":"Processing a skaffold.yaml where a customAction's executionMode config sets both the kubernetesCluster sub-config and the local sub-config simultaneously.","commonSituations":"Copy-pasting executionMode blocks between actions and keeping both variants; merging config files that each set a different execution mode; experimenting with local runs then switching to cluster runs without deleting the old block.","solutions":["Remove one of the two execution mode blocks so only kubernetesCluster or local remains","Decide the intended execution target for the action and keep only that block","Re-run the skaffold command to confirm validation passes"],"exampleFix":"# before\ncustomActions:\n- name: db-migrate\n  executionMode:\n    kubernetesCluster: {}\n    local: {}\n# after\ncustomActions:\n- name: db-migrate\n  executionMode:\n    kubernetesCluster: {}","handlingStrategy":"validation","validationCode":"func singleExecMode(action CustomAction) error {\n\tset := 0\n\tif action.ExecutionMode.KubernetesCluster != nil { set++ }\n\tif action.ExecutionMode.Local != nil { set++ }\n\tif set > 1 {\n\t\treturn fmt.Errorf(\"custom action %q sets both cluster and local execution modes\", action.Name)\n\t}\n\treturn nil\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Keep exactly one executionMode block per custom action","When switching local↔cluster, delete the old block in the same change","Review merges that combine executionMode blocks from different branches"],"tags":["skaffold","yaml-validation","custom-actions","execution-mode"],"backgroundTag":"schema-validation-failed","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}