XTLS/Xray-core · error

invalid variable name

Error message

invalid variable name

What it means

validateCustomVarName (infra/conf/transport_finalmask.go:374) checks every "capture" and "reuse" variable name in header-custom TCP/UDP masks against ^[A-Za-z_][A-Za-z0-9_]*$. Empty is allowed (no-op); anything else — spaces, dashes, digits first, non-ASCII, $ prefixes — returns "invalid variable name".

Source

Thrown at infra/conf/transport_finalmask.go:374

	Op   string               `json:"op"`
	Args []CustomTransformArg `json:"args"`
}

type CustomTransformArg struct {
	Type      string           `json:"type"`
	Bytes     json.RawMessage  `json:"bytes"`
	U64       *uint64          `json:"u64"`
	Reuse     string           `json:"reuse"`
	Metadata  string           `json:"metadata"`
	Transform *CustomTransform `json:"transform"`
}

func validateCustomVarName(name string) error {
	if name == "" {
		return nil
	}
	if !customVarNamePattern.MatchString(name) {
		return errors.New("invalid variable name")
	}
	return nil
}

func validateCustomItemSpec(capture string, packet json.RawMessage, rand int32, reuse string, transform *CustomTransform) error {
	if err := validateCustomVarName(capture); err != nil {
		return err
	}
	if err := validateCustomVarName(reuse); err != nil {
		return err
	}

	kindCount := 0
	if len(packet) > 0 {
		kindCount++
	}
	if rand > 0 {
		kindCount++

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Use plain C-style identifiers: letter or underscore first, then letters/digits/underscores
  2. Drop sigils: "$payload" -> "payload"; "first-packet" -> "first_packet"
  3. Leave capture/reuse empty when the item neither saves nor loads a variable

Example fix

// before
{ "capture": "$hello", "packet": [72,105] }
// after
{ "capture": "hello", "packet": [72,105] }
Defensive patterns

Strategy: type-guard

Validate before calling

const IDENT = /^[A-Za-z_][A-Za-z0-9_]*$/;
for (const it of items) {
  if (it.capture && !IDENT.test(it.capture)) throw new Error(`bad capture name: ${it.capture}`);
  if (it.reuse && !IDENT.test(it.reuse)) throw new Error(`bad reuse name: ${it.reuse}`);
}

Type guard

const isVarName = (s: string) => s === '' || /^[A-Za-z_][A-Za-z0-9_]*$/.test(s);

Prevention

When it happens

Trigger: An item with "capture":"pkt 1", "reuse":"$var", "capture":"1st", or names using '-' instead of '_'. Runs during validateCustomItemSpec for every clients/servers/errors (TCP) and client/server (UDP) item.

Common situations: Users writing shell-style ($VAR) or template-style ({var}) names; regex-derived names with special characters; translating examples from another language's identifier rules.

Related errors


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