XTLS/Xray-core · error

failed to decode config:

Error message

failed to decode config: 

What it means

The JSON loader successfully read the input but serial.DecodeJSONConfig could not parse it into a *conf.Config. This is a syntax-level or structure-level JSON failure: invalid JSON, wrong types for Xray fields, or (when strict mode is enabled via serial.UseStrictJSON in the io.Reader branch) unknown/duplicate fields. The parse error is chained as the Base cause with line/column information.

Source

Thrown at main/json/json.go:32

)

func init() {
	common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
		Name:      "JSON",
		Extension: []string{"json"},
		Loader: func(input interface{}) (*core.Config, error) {
			switch v := input.(type) {
			case cmdarg.Arg:
				cf := &conf.Config{}
				for i, arg := range v {
					errors.LogInfo(context.Background(), "Reading config: ", arg)
					r, err := confloader.LoadConfig(arg)
					if err != nil {
						return nil, errors.New("failed to read config: ", arg).Base(err)
					}
					c, err := serial.DecodeJSONConfig(r)
					if err != nil {
						return nil, errors.New("failed to decode config: ", arg).Base(err)
					}
					if i == 0 {
						// This ensure even if the muti-json parser do not support a setting,
						// It is still respected automatically for the first configure file
						*cf = *c
						continue
					}
					cf.Override(c, arg)
				}
				return cf.Build()
			case io.Reader:
				if serial.UseStrictJSON {
					cfg, err := serial.DecodeJSONConfigStrict(v)
					if err != nil {
						return nil, err
					}
					return cfg.Build()
				}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Validate the file with a JSON linter: jq empty config.json shows exact line/column of the error
  2. Remove comments and trailing commas; quote all keys; use numbers for ports
  3. Cross-check field names/types against Xray's JSON config schema (infra/conf)
  4. Rename the file to .yaml/.toml only if the content really is that format, so the right loader parses it

Example fix

// before
{
  "inbounds": [{ "port": "443", "protocol": "dokodemo-door" }]  // port as string, comment
}

// after
{
  "inbounds": [{ "port": 443, "protocol": "dokodemo-door" }]
}
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate before handing to Xray
if data, err := os.ReadFile(cfgPath); err == nil {
    if !json.Valid(data) { log.Fatalf("invalid JSON in %s", cfgPath) }
}

Try / catch

if err := load(); err != nil {
    var syn *json.SyntaxError
    if errors.As(err, &syn) { pointAt(cfgPath, int(syn.Offset)) }
}

Prevention

When it happens

Trigger: Trailing commas, unquoted keys, comments in JSON, mismatched braces in a .json config; or values of the wrong type (string where number expected). With strict mode: fields not defined in the schema, such as legacy v2ray keys removed in Xray.

Common situations: Hand-editing JSON configs and breaking syntax, pasting YAML or TOML snippets into a .json file, port written as string "443" instead of number, or migrating configs between v2ray and Xray with incompatible keys.

Understand the failure class

Related errors


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