{"record":{"id":"67bbf94fae757046","repo":"Tencent/WeKnora","slug":"create-doris-client-w","errorCode":null,"errorMessage":"create doris client: %w","messagePattern":"create doris client: %w","errorType":"exception","errorClass":null,"httpStatus":500,"severity":"error","filePath":"internal/container/engine_factory.go","lineNumber":351,"sourceCode":"\t\treturn nil, fmt.Errorf(\"doris connection requires addr (host:port)\")\n\t}\n\tif cc.Database == \"\" {\n\t\treturn nil, fmt.Errorf(\"doris connection requires database\")\n\t}\n\n\tmc := mysql.NewConfig()\n\tmc.User = cc.Username\n\tmc.Passwd = cc.Password\n\tutils.RegisterMySQLSSRFDialer()\n\tmc.Net = utils.MySQLSSRFNetwork\n\tmc.Addr = cc.Addr\n\tmc.DBName = cc.Database\n\tmc.Params = map[string]string{\"charset\": \"utf8mb4\"}\n\tmc.ParseTime = true\n\tmc.Loc = time.Local\n\tdb, err := sql.Open(\"mysql\", mc.FormatDSN())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create doris client: %w\", err)\n\t}\n\tdb.SetMaxOpenConns(20)\n\tdb.SetMaxIdleConns(5)\n\tdb.SetConnMaxLifetime(time.Hour)\n\n\thttpPort := cc.HTTPPort\n\tif httpPort <= 0 {\n\t\thttpPort = 8030\n\t}\n\thttpBase := \"http://\" + hostFromAddr(cc.Addr) + \":\" + strconv.Itoa(httpPort)\n\n\trepo := dorisRepo.NewDorisRetrieveEngineRepository(\n\t\tdb, httpBase, cc.Username, cc.Password, cc.Database, &store.IndexConfig,\n\t)\n\treturn retriever.NewKVHybridRetrieveEngine(repo, types.DorisRetrieverEngineType), nil\n}\n\n// hostFromAddr 从 \"host:port\" 中拆出 host 部分；Addr 没有冒号时整段当作 host。","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/container/engine_factory.go#L333-L369","documentation":"This wraps an error from sql.Open(\"mysql\", mc.FormatDSN()) when building the Doris MySQL-protocol client. sql.Open validates the DSN format and driver availability but does not connect; failures indicate a malformed DSN (bad host/port/user chars, invalid params) or the mysql driver not being registered.","triggerScenarios":"createDorisEngine building a DSN from ConnectionConfig where Addr, Username, Password, or Database contain DSN-invalid characters (unescaped '@', ':', '/', '(' ')'), or the go-sql-driver/mysql driver was never imported/registered under the name \"mysql\".","commonSituations":"Passwords with special characters not escaped in the DSN; Addr containing a scheme or trailing slash; forgetful refactors dropping the driver's blank import (underscore import) after dependency cleanup.","solutions":["Escape credentials with url.UserPassword or rely on mc.User/mc.Passwd (Config.FormatDSN escapes) instead of string-building the DSN","Ensure Addr is pure host:port with no scheme or path","Confirm the blank import _ \"github.com/go-sql-driver/mysql\" exists so the driver registers","Note sql.Open does not connect: if you actually see connection failures at query time, check reachability of fe-host:9030 separately"],"exampleFix":"// before\ndb, err := sql.Open(\"mysql\", fmt.Sprintf(\"%s:%s@tcp(%s)/%s\", user, rawPass, addr, dbname)) // rawPass with '@' breaks DSN\n// after\nmc := mysql.NewConfig()\nmc.User = user\nmc.Passwd = rawPass\nmc.Net = \"tcp\"\nmc.Addr = addr\nmc.DBName = dbname\ndb, err := sql.Open(\"mysql\", mc.FormatDSN())","handlingStrategy":"validation","validationCode":"func validDorisDSNParts(cc types.ConnectionConfig) error {\n    if _, _, err := net.SplitHostPort(cc.Addr); err != nil { return err }\n    for _, r := range cc.Username + cc.Password { if strings.ContainsRune(\"@:/() \", r) { return fmt.Errorf(\"credential char %q needs escaping\", r) } }\n    return nil\n}","typeGuard":"func dorisDSNReady(cc types.ConnectionConfig) bool { return validDorisDSNParts(cc) == nil }","tryCatchPattern":"db, err := sql.Open(\"mysql\", mc.FormatDSN())\nvar derr *driver.ErrInvalidDSN // or check wrapped error\nif err != nil {\n    return fmt.Errorf(\"doris DSN invalid — check addr/credentials escaping and mysql driver import: %w\", err)\n}\nif err := db.PingContext(ctx); err != nil { return fmt.Errorf(\"doris unreachable at %s: %w\", cc.Addr, err) }","preventionTips":["Use mysql.Config + FormatDSN instead of hand-built DSN strings so credentials are escaped","Keep the blank import _ \"github.com/go-sql-driver/mysql\" intact","Remember sql.Open does not connect; add an immediate Ping in health checks","Keep Addr as bare host:port with no scheme or trailing slash"],"tags":["doris","mysql","dsn","sql-open","config"],"backgroundTag":"invalid-dsn","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}