{"record":{"id":"b3d1bffed71854de","repo":"XTLS/Xray-core","slug":"failed-to-parse-yaml-config","errorCode":null,"errorMessage":"failed to parse yaml config","messagePattern":"failed to parse yaml config","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/serial/loader.go","lineNumber":165,"sourceCode":"\t}\n\n\tjsonFile, err := yaml.YAMLToJSON(yamlFile)\n\tif err != nil {\n\t\treturn nil, errors.New(\"failed to convert yaml to json\").Base(err)\n\t}\n\n\treturn DecodeJSONConfig(bytes.NewReader(jsonFile))\n}\n\nfunc LoadYAMLConfig(reader io.Reader) (*core.Config, error) {\n\tyamlConfig, err := DecodeYAMLConfig(reader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpbConfig, err := yamlConfig.Build()\n\tif err != nil {\n\t\treturn nil, errors.New(\"failed to parse yaml config\").Base(err)\n\t}\n\n\treturn pbConfig, nil\n}\n","sourceCodeStart":147,"sourceCodeEnd":170,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/serial/loader.go#L147-L170","documentation":"LoadYAMLConfig decodes a YAML document into the intermediate JSON config structure and then calls Build() to convert it to the protobuf core.Config. This error wraps any failure emitted during that conversion, such as unknown fields, invalid inbound/outbound settings, or a nested builder failing. The '.Base(err)' chain preserves the underlying cause, so the real problem is in the wrapped error, not this message.","triggerScenarios":"Calling infra/conf.LoadYAMLConfig (or LoadConfig with a .yml/.yaml file, or xray run -c config.yaml) where the YAML parses syntactically but contains semantically invalid values: an unknown protocol name, a bad address string, or invalid per-protocol settings that fail during Build().","commonSituations":"Hand-edited YAML configs with typo'd keys or wrong value types; porting a JSON example to YAML and mangling structure; forgetting that YAML keys are case-sensitive and that 'inbounds'/'outbounds' entries require a valid 'protocol'.","solutions":["Inspect the wrapped cause (err via errors.GetBase / printing the full chain) — it names the actual field or builder that failed.","Validate the YAML against the current Xray JSON/YAML schema, checking every 'protocol', 'settings' object, and address field.","Reproduce with the equivalent JSON config to confirm which section is broken, then fix that section in the YAML.","Check version compatibility: fields from a newer Xray version will fail Build() on an older binary."],"exampleFix":"// before (config.yaml uses an unknown field)\ninbounds:\n  - protocol: dokodemo-door\n    settings:\n      addres: 127.0.0.1   # typo, and unknown to builder\n\n// after\ninbounds:\n  - protocol: dokodemo-door\n    settings:\n      address: 127.0.0.1\n      port: 1080","handlingStrategy":"try-catch","validationCode":"// Validate YAML maps to expected shape before LoadYAMLConfig\nimport \"gopkg.in/yaml.v3\"\n\nfunc checkYAMLShape(raw []byte) error {\n\tvar top map[string]any\n\tif err := yaml.Unmarshal(raw, &top); err != nil {\n\t\treturn err\n\t}\n\tfor _, key := range []string{\"inbounds\", \"outbounds\"} {\n\t\tfor _, item := range top[key].([]any) {\n\t\t\tm := item.(map[string]any)\n\t\t\tif _, ok := m[\"protocol\"]; !ok {\n\t\t\t\treturn fmt.Errorf(\"%s entry missing protocol\", key)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"pbConf, err := conf.LoadYAMLConfig(f)\nif err != nil {\n    // Walk the Base chain to surface the real builder failure\n    log.Fatalf(\"config load failed: %v\", err)\n}","preventionTips":["Lint config in CI with a schema validator before deploy","Keep a known-good config in version control and diff after edits","Use JSON configs where tooling/IDE validation is stronger"],"tags":["config","yaml","xray","startup"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}