{"record":{"id":"edb4f04155368c3b","repo":"AlistGo/alist","slug":"tls-config-not-provided","errorCode":null,"errorMessage":"TLS config not provided","messagePattern":"TLS config not provided","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/ftp.go","lineNumber":153,"sourceCode":"\tif userObj.Disabled || !common.HasPermission(perm, common.PermFTPAccess) {\n\t\treturn nil, errors.New(\"user is not allowed to access via FTP\")\n\t}\n\n\tctx := context.Background()\n\tctx = context.WithValue(ctx, \"user\", userObj)\n\tif user == \"anonymous\" || user == \"guest\" {\n\t\tctx = context.WithValue(ctx, \"meta_pass\", pass)\n\t} else {\n\t\tctx = context.WithValue(ctx, \"meta_pass\", \"\")\n\t}\n\tctx = context.WithValue(ctx, \"client_ip\", cc.RemoteAddr().String())\n\tctx = context.WithValue(ctx, \"proxy_header\", d.proxyHeader)\n\treturn ftp.NewAferoAdapter(ctx), nil\n}\n\nfunc (d *FtpMainDriver) GetTLSConfig() (*tls.Config, error) {\n\tif d.tlsConfig == nil {\n\t\treturn nil, errors.New(\"TLS config not provided\")\n\t}\n\treturn d.tlsConfig, nil\n}\n\nfunc (d *FtpMainDriver) Stop() {\n\td.isShutdown = true\n\td.shutdownLock.Lock()\n\tdefer d.shutdownLock.Unlock()\n\tfor _, value := range d.clients {\n\t\t_ = value.Close()\n\t}\n}\n\nfunc lookupIP(host string) string {\n\tif host == \"\" || net.ParseIP(host) != nil {\n\t\treturn host\n\t}\n\tips, err := net.LookupIP(host)","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/server/ftp.go#L135-L171","documentation":"Returned by FtpMainDriver.GetTLSConfig when the server was constructed without a tls.Config, which happens when getTlsConf() failed or was never given certificate paths. The ftpserver library calls this driver hook when a client issues AUTH TLS, so this error surfaces as the FTPS handshake failing.","triggerScenarios":"Client sends 'AUTH TLS'/'AUTH SSL' on the control channel while the ftp.tls_cert_file / ftp.tls_key_file settings are unset or the files could not be loaded at server start.","commonSituations":"Admin enabled the FTPS listener port but forgot to configure the TLS certificate and private key paths; cert file present but unreadable due to permissions, so the driver silently started without TLS; using FTPS against a plain-FTP-only deployment.","solutions":["Set both ftp tls certificate and private key file paths in the FTP settings (they are only valid as a pair)","Verify the files are readable by the AList process and contain a matching cert/key pair (openssl x509 / openssl pkey)","If TLS is not intended, reconfigure the client to use plain FTP instead of AUTH TLS"],"exampleFix":"// before: settings lack TLS material\nftp:\n  tls_cert_file: \"\"\n  tls_key_file: \"\"\n// after\nftp:\n  tls_cert_file: \"/etc/alist/cert.pem\"\n  tls_key_file: \"/etc/alist/key.pem\"","handlingStrategy":"validation","validationCode":"// Before enabling the FTPS listener, verify both cert files load\n_, err := getTlsConf(cfg.FTP.TLSKeyFile, cfg.FTP.TLSCertFile)\nif err != nil {\n    log.Fatalf(\"FTPS not configured: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"tlsConf, err := driver.GetTLSConfig()\nif err != nil {\n    if strings.Contains(err.Error(), \"TLS config not provided\") {\n        // fall back to plain FTP or fail fast with a config hint\n    }\n    return err\n}","preventionTips":["Configure cert + key as a pair; validate them at startup, not at first AUTH TLS","Monitor file permissions on cert/key paths across restarts","Test with 'lftp -e \"set ftp:ssl-force true; open host\"' after any TLS change"],"tags":["ftp","ftp-tls","certificates","config"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}