hashicorp/nomad · error

Required and optional meta keys should be disjoint. Followin

Error message

Required and optional meta keys should be disjoint. Following keys exist in both: %v

What it means

ParameterizedJobConfig.Validate requires that MetaRequired and MetaOptional are disjoint sets, verified with helper.IsDisjoint. If any key appears in both lists, this error lists the offending keys, since a dispatch meta key cannot simultaneously be mandatory and optional.

Source

Thrown at nomad/structs/structs.go:6095

	// MetaRequired is metadata keys that must be specified by the dispatcher
	MetaRequired []string

	// MetaOptional is metadata keys that may be specified by the dispatcher
	MetaOptional []string
}

func (d *ParameterizedJobConfig) Validate() error {
	var mErr multierror.Error
	switch d.Payload {
	case DispatchPayloadOptional, DispatchPayloadRequired, DispatchPayloadForbidden:
	default:
		_ = multierror.Append(&mErr, fmt.Errorf("Unknown payload requirement: %q", d.Payload))
	}

	// Check that the meta configurations are disjoint sets
	disjoint, offending := helper.IsDisjoint(d.MetaRequired, d.MetaOptional)
	if !disjoint {
		_ = multierror.Append(&mErr, fmt.Errorf("Required and optional meta keys should be disjoint. Following keys exist in both: %v", offending))
	}

	return mErr.ErrorOrNil()
}

func (d *ParameterizedJobConfig) Canonicalize() {
	if d.Payload == "" {
		d.Payload = DispatchPayloadOptional
	}
}

func (d *ParameterizedJobConfig) Copy() *ParameterizedJobConfig {
	if d == nil {
		return nil
	}
	nd := new(ParameterizedJobConfig)
	*nd = *d
	nd.MetaOptional = slices.Clone(nd.MetaOptional)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the duplicated key(s) named in the error from either meta_required or meta_optional.
  2. Decide per key whether dispatch callers must supply it (required) or may supply it (optional).
  3. Add a config lint that asserts the two key lists are disjoint before submission.
  4. Use `nomad job validate` to verify the corrected job.

Example fix

// before
parameterized_job {
  meta_required  = ["env"]
  meta_optional  = ["env", "region"]
}
// after
parameterized_job {
  meta_required  = ["env"]
  meta_optional  = ["region"]
}
Defensive patterns

Strategy: validation

Validate before calling

func metaKeysDisjoint(req, opt []string) bool {
    set := make(map[string]struct{}, len(req))
    for _, k := range req {
        set[k] = struct{}{}
    }
    for _, k := range opt {
        if _, ok := set[k]; ok {
            return false
        }
    }
    return true
}
// call before submitting: if !metaKeysDisjoint(pj.MetaRequired, pj.MetaOptional) { ... }

Try / catch

if err := job.ParameterizedJob.Validate(); err != nil {
    if strings.Contains(err.Error(), "should be disjoint") {
        // dedupe the offending keys reported in the message
    }
}

Prevention

When it happens

Trigger: Submitting a parameterized job whose parameter_meta block declares the same key in both required_keys and optional_keys (e.g. meta_required = ["env"], meta_optional = ["env"]).

Common situations: Accumulating meta keys over time without deduplicating; merging two job templates where one lists a key as required and the other as optional; copy-paste of key lists.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/99667792e915a8ab. Report an issue: GitHub.