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
- Keep exactly one of: packet, rand(>0), reuse, or transform per item
- If you need both a packet and computed bytes, make them two sequential items
- 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
- Think of each item as exactly one producer
- Never leave leftover producer fields when switching an item's role
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
- invalid randRange
- invalid variable name
- transform op is required
- transform args are required
- transform arg must set exactly one value
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/839a0c8c661580cb.
Report an issue: GitHub.