XTLS/Xray-core · error

exactly one item kind must be set

Error message

exactly one item kind must be set

What it means

validateCustomItemSpec (infra/conf/transport_finalmask.go:401) counts how many 'kinds' a header-custom item sets among packet, rand>0, reuse, and transform. More than one kind returns "exactly one item kind must be set": an item must be a single, unambiguous producer of bytes or a variable reference.

Source

Thrown at infra/conf/transport_finalmask.go:401

	if err := validateCustomVarName(reuse); err != nil {
		return err
	}

	kindCount := 0
	if len(packet) > 0 {
		kindCount++
	}
	if rand > 0 {
		kindCount++
	}
	if reuse != "" {
		kindCount++
	}
	if transform != nil {
		kindCount++
	}
	if kindCount > 1 {
		return errors.New("exactly one item kind must be set")
	}
	if kindCount == 0 && capture != "" {
		return errors.New("exactly one item kind must be set")
	}

	return nil
}

func buildCustomTransform(transform *CustomTransform) (*custom.Expr, error) {
	if transform == nil {
		return nil, nil
	}
	if transform.Op == "" {
		return nil, errors.New("transform op is required")
	}
	if len(transform.Args) == 0 {
		return nil, errors.New("transform args are required")
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Keep exactly one of: packet, rand(>0), reuse, or transform per item
  2. If you need both a packet and computed bytes, make them two sequential items
  3. Re-read each item after editing and delete unused producer fields

Example fix

// before
{ "packet": [1,2,3], "rand": 8 }
// after
{ "packet": [1,2,3] }
// next item: { "rand": 8 }
Defensive patterns

Strategy: validation

Validate before calling

function kinds(it:any){
  let n = 0;
  if (it.packet != null && it.packet !== '' && !(Array.isArray(it.packet)&&it.packet.length===0)) n++;
  if ((it.rand ?? 0) > 0) n++;
  if (it.reuse) n++;
  if (it.transform) n++;
  return n;
}
for (const it of items) if (kinds(it) > 1) throw new Error('item sets multiple kinds');

Type guard

const hasSingleKind = (it:any) => kinds(it) === 1;

Prevention

When it happens

Trigger: An item like {"packet":[1],"rand":5} (packet + rand), {"reuse":"v","transform":{...}}, or {"packet":[1],"reuse":"v"}. Combinations with capture are fine as long as exactly one producer kind is present.

Common situations: Kitchen-sink templates filling every field; incremental editing where a transform is added without removing the old packet; copy-pasting an example item and toggling fields on.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/839a0c8c661580cb. Report an issue: GitHub.