{"record":{"id":"287cb4c59ac88c38","repo":"XTLS/Xray-core","slug":"failed-to-build-tls-config","errorCode":null,"errorMessage":"Failed to build TLS config.","messagePattern":"Failed to build TLS config\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_internet.go","lineNumber":94,"sourceCode":"\t}\n\tif c.Network != nil {\n\t\tprotocol, err := c.Network.Build()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tconfig.ProtocolName = protocol\n\t}\n\n\tswitch strings.ToLower(c.Security) {\n\tcase \"\", \"none\":\n\tcase \"tls\":\n\t\ttlsSettings := c.TLSSettings\n\t\tif tlsSettings == nil {\n\t\t\ttlsSettings = &TLSConfig{}\n\t\t}\n\t\tts, err := tlsSettings.Build()\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Failed to build TLS config.\").Base(err)\n\t\t}\n\t\ttm := serial.ToTypedMessage(ts)\n\t\tconfig.SecuritySettings = append(config.SecuritySettings, tm)\n\t\tconfig.SecurityType = tm.Type\n\tcase \"reality\":\n\t\tif config.ProtocolName != \"tcp\" && config.ProtocolName != \"splithttp\" && config.ProtocolName != \"grpc\" {\n\t\t\treturn nil, errors.New(\"REALITY only supports RAW, XHTTP and gRPC for now.\")\n\t\t}\n\t\tif c.REALITYSettings == nil {\n\t\t\treturn nil, errors.New(`REALITY: Empty \"realitySettings\".`)\n\t\t}\n\t\tts, err := c.REALITYSettings.Build()\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"Failed to build REALITY config.\").Base(err)\n\t\t}\n\t\ttm := serial.ToTypedMessage(ts)\n\t\tconfig.SecuritySettings = append(config.SecuritySettings, tm)\n\t\tconfig.SecurityType = tm.Type","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_internet.go#L76-L112","documentation":"Wrapper thrown by StreamConfig security building when streamSettings.security is \"tls\" and the nested tlsSettings object fails its own Build(). The original TLS error is attached via .Base(err); the real cause is inside the TLSConfig build (bad certificates, invalid ALPN, etc.). If tlsSettings is absent an empty TLSConfig{} is built, so this can also surface defaults validation.","triggerScenarios":"security:\"tls\" together with malformed certificate paths, invalid ALPN entries, or bad key values inside tlsSettings; omitted tlsSettings that still fails default validation.","commonSituations":"Wrong certificate file paths after moving configs; PEM blocks pasted with corruption; ALPN values not in the allowed list.","solutions":["Inspect the wrapped/base error for the underlying TLS cause and fix that field.","Validate certificate files exist and parse as PEM before starting.","If TLS is not intended, set security to \"none\" or remove the tlsSettings block."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := streamCfg.Build(); err != nil {\n    if strings.Contains(err.Error(), \"Failed to build TLS config\") {\n        // unwrap errors.Unwrap(err) to reach the concrete TLS cause and report it\n    }\n    return err\n}","preventionTips":["Pre-parse certificate files with tls.LoadX509KeyPair in a pre-flight step.","Always log the chained base error, not just the wrapper message.","Validate ALPN entries against the allowed list before build."],"tags":["go","xray","config","tls","error-chaining"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}