GoogleContainerTools/skaffold · error

only one element in set %s can be set. got %s and %s

Error message

only one element in set %s can be set. got %s and %s

What it means

For fields in a oneOf set (mutually exclusive config alternatives), oneOfTag.Process verifies no sibling field of the same set is also non-zero. If two members are set (e.g. both `docker` and `kaniko` build strategies, or two execution modes), it returns 'only one element in set %s can be set', naming the set and the two conflicting fields.

Source

Thrown at pkg/skaffold/yamltags/tags.go:235

	}
	oot.oneOfSets[oot.setName][oot.Field.Name] = struct{}{}
	return nil
}

func (oot *oneOfTag) Process(val reflect.Value) error {
	if isZeroValue(val) {
		return nil
	}

	// This must exist because process is always called after Load.
	oneOfSet := oot.oneOfSets[oot.setName]
	for otherField := range oneOfSet {
		if otherField == oot.Field.Name {
			continue
		}
		field := oot.Parent.FieldByName(otherField)
		if !isZeroValue(field) {
			return fmt.Errorf("only one element in set %s can be set. got %s and %s", oot.setName, otherField, oot.Field.Name)
		}
	}
	return nil
}

type skipTrimTag struct {
	Field reflect.StructField
}

func (tag *skipTrimTag) Load(s []string) error {
	return nil
}

func (tag *skipTrimTag) Process(val reflect.Value) error {
	if isZeroValue(val) {
		if tags, ok := tag.Field.Tag.Lookup("yaml"); ok {
			return fmt.Errorf("skipTrim value not set: %s", strings.Split(tags, ",")[0])
		}

View on GitHub (pinned to a1189de023)

Solutions

  1. Remove one of the two fields named in the error from skaffold.yaml, keeping the alternative you intend
  2. Comment out the unused strategy block rather than leaving empty-looking keys that may parse as set
  3. Use `skaffold fix` or `skaffold init` to regenerate a valid single-choice config
  4. Check indentation — a misnested key can accidentally land in the sibling field's position

Example fix

// before (skaffold.yaml) — both set
build:
  artifacts:
    - image: foo
  kaniko: {}
  docker: {}
// after
build:
  artifacts:
    - image: foo
  docker: {}
Defensive patterns

Strategy: validation

Validate before calling

// ensure only one member of a oneOf set is present in the decoded config
func oneOfSet(m map[string]interface{}, members []string) error {
    var set []string
    for _, k := range members {
        if v, ok := m[k]; ok && v != nil && v != "" {
            set = append(set, k)
        }
    }
    if len(set) > 1 {
        return fmt.Errorf("only one of %v can be set; got %v", members, set)
    }
    return nil
}

Type guard

func exactlyOneSet(flags ...bool) bool {
    n := 0
    for _, f := range flags { if f { n++ } }
    return n == 1
}

Try / catch

if err != nil && strings.Contains(err.Error(), "only one element in set") {
    // parse set + two field names from the message, drop the unwanted one from config
}

Prevention

When it happens

Trigger: A decoded skaffold.yaml supplies values for two fields that belong to the same oneOf set on a struct (e.g. both `exec` and `docker` in a build execution environment, or both `docker` and `kubernetesCluster` execution modes for verify), then validation runs.

Common situations: Merging config files/snippets and keeping both alternatives; leftover key from a previous strategy plus a newly added one; auto-generated config setting defaults alongside user overrides.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/ca89e86972f1fffd. Report an issue: GitHub.