XTLS/Xray-core · error

unknown format of a string list:

Error message

unknown format of a string list: 

What it means

Thrown by StringList.UnmarshalJSON in infra/conf/common.go when a JSON value expected to be a string list can be parsed neither as a JSON array of strings nor as a single comma-separated string. Xray first tries json.Unmarshal into []string, then into a raw string split on ','. If both fail (the value is a number, boolean, object, or null), this error is returned. The offending raw JSON data is appended to the message.

Source

Thrown at infra/conf/common.go:41

func (v StringList) Len() int {
	return len(v)
}

// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (v *StringList) UnmarshalJSON(data []byte) error {
	var strarray []string
	if err := json.Unmarshal(data, &strarray); err == nil {
		*v = *NewStringList(strarray)
		return nil
	}

	var rawstr string
	if err := json.Unmarshal(data, &rawstr); err == nil {
		strlist := strings.Split(rawstr, ",")
		*v = *NewStringList(strlist)
		return nil
	}
	return errors.New("unknown format of a string list: " + string(data))
}

type Address struct {
	net.Address
}

// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
func (v *Address) MarshalJSON() ([]byte, error) {
	return json.Marshal(v.Address.String())
}

// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (v *Address) UnmarshalJSON(data []byte) error {
	var rawStr string
	if err := json.Unmarshal(data, &rawStr); err != nil {
		return errors.New("invalid address: ", string(data)).Base(err)
	}
	if strings.HasPrefix(rawStr, "env:") {

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Change the JSON value to an array of strings, e.g. "inboundTag": ["tag1","tag2"]
  2. Or supply a single comma-separated string, e.g. "inboundTag": "tag1,tag2"
  3. Check the error suffix (the raw JSON data) to identify exactly which field produced it
  4. Validate the whole config with `xray run -test -c config.json` or an JSON schema linter before deployment

Example fix

// before
"inboundTag": 123

// after
"inboundTag": ["123"]
Defensive patterns

Strategy: validation

Validate before calling

// before unmarshaling, assert the JSON value is a string or array of strings
func isStringListJSON(raw []byte) bool {
    var arr []string
    if json.Unmarshal(raw, &arr) == nil {
        return true
    }
    var s string
    return json.Unmarshal(raw, &s) == nil
}

Try / catch

if err := json.Unmarshal(data, &stringList); err != nil {
    if strings.Contains(err.Error(), "unknown format of a string list") {
        // log the raw field value and point the user at the array/comma-string forms
    }
    return fmt.Errorf("config field %q: %w", fieldName, err)
}

Prevention

When it happens

Trigger: Any config field typed conf.StringList (e.g. inbound/outbound 'tag' arrays, 'allocStrategy' fallbacks, 'certificates' arrays in some versions, routing 'network' is separate) receiving a non-string JSON type. Examples: "inboundTag": 123, "domain": {"type":"x"}, or "address": [1,2] where array elements are not strings.

Common situations: YAML-to-JSON config conversion mistakes where a scalar stays unquoted and becomes a number or boolean; passing an object where a list of domain strings is expected; trailing commas or malformed JSON that makes the array unmarshal fail while the string fallback also fails.

Related errors


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