XTLS/Xray-core · error
transform arg must set exactly one value
Error message
transform arg must set exactly one value
What it means
buildCustomTransformArg (infra/conf/transport_finalmask.go:454) counts the value fields set on a transform argument — str, bytes, u64, reuse, metadata, transform — and requires exactly one. Zero set, or two or more set, returns "transform arg must set exactly one value"; an arg is a tagged union, not a record.
Source
Thrown at infra/conf/transport_finalmask.go:454
func buildCustomTransformArg(arg CustomTransformArg) (*custom.ExprArg, error) {
kindCount := 0
if len(arg.Bytes) > 0 {
kindCount++
}
if arg.U64 != nil {
kindCount++
}
if arg.Reuse != "" {
kindCount++
}
if arg.Metadata != "" {
kindCount++
}
if arg.Transform != nil {
kindCount++
}
if kindCount != 1 {
return nil, errors.New("transform arg must set exactly one value")
}
if len(arg.Bytes) > 0 {
value, err := PraseByteSlice(arg.Bytes, arg.Type)
if err != nil {
return nil, err
}
return &custom.ExprArg{
Value: &custom.ExprArg_Bytes{
Bytes: value,
},
}, nil
}
if arg.U64 != nil {
return &custom.ExprArg{
Value: &custom.ExprArg_U64{
U64: *arg.U64,
},View on GitHub (pinned to 7d214f8b09)
Solutions
- Set exactly one value field per arg object
- Chain multiple values as multiple args consumed by the op instead of one arg with several fields
- Remove default/placeholder entries like "u64":0 — even an explicit zero counts as set
Example fix
// before
"args": [ { "str": "id-", "u64": 0 } ]
// after
"args": [ { "str": "id-" }, { "u64": 7 } ] Defensive patterns
Strategy: validation
Validate before calling
const ARG_FIELDS = ['str','bytes','u64','reuse','metadata','transform'];
for (const a of t.args ?? []) {
const set = ARG_FIELDS.filter(k => a[k] !== undefined && a[k] !== null);
if (set.length !== 1) throw new Error(`arg must set exactly one of ${ARG_FIELDS}, set: ${set}`);
} Type guard
const isSingleValueArg = (a:any) => ARG_FIELDS.filter(k => a[k] !== undefined && a[k] !== null).length === 1;
Prevention
- Treat transform args as a tagged union
- Omit unused fields entirely; explicit zeros count as set
When it happens
Trigger: {} as an arg; {"str":"a","reuse":"b"}; {"bytes":"...","u64":1}. Note bytes+type is fine because type is a decoder hint, not a value; but any two value fields together fail.
Common situations: Copy-pasting arg templates and leaving placeholder values; adding a fallback value 'just in case'; treating args as a struct where you fill several fields.
Related errors
- transform op is required
- transform args are required
- invalid randRange
- invalid variable name
- exactly one item kind must be set
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/33c86b81f54fad02.
Report an issue: GitHub.