{"record":{"id":"7875a51d31611ece","repo":"mattermost-community/focalboard","slug":"searchboardsforuser-error-getting-unionsql-w","errorCode":null,"errorMessage":"SearchBoardsForUser error getting unionSQL: %w","messagePattern":"SearchBoardsForUser error getting unionSQL: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/store/mattermostauthlayer/mattermostauthlayer.go","lineNumber":774,"sourceCode":"\t}\n\t// NOTE: theoretically, could do e.g. `isGuest := !includePublicBoards`\n\t// but that introduces some tight coupling + fragility\n\tif !user.IsGuest {\n\t\tunionQ = unionQ.\n\t\t\tPrefix(\"(\").\n\t\t\tSuffix(\") UNION (\"+channelMembersSQL+\")\", channelMembersArgs...)\n\t\tif includePublicBoards {\n\t\t\tunionQ = unionQ.Suffix(\" UNION (\"+teamMembersSQL+\")\", teamMembersArgs...)\n\t\t}\n\t} else if includePublicBoards {\n\t\tunionQ = unionQ.\n\t\t\tPrefix(\"(\").\n\t\t\tSuffix(\") UNION (\"+teamMembersSQL+\")\", teamMembersArgs...)\n\t}\n\n\tunionSQL, unionArgs, err := unionQ.ToSql()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"SearchBoardsForUser error getting unionSQL: %w\", err)\n\t}\n\n\t// if we're using postgres or sqlite, we need to replace the\n\t// question mark placeholder with the numbered dollar one, now\n\t// that the full query is built\n\tif s.dbType == model.PostgresDBType || s.dbType == model.SqliteDBType {\n\t\tvar rErr error\n\t\tunionSQL, rErr = sq.Dollar.ReplacePlaceholders(unionSQL)\n\t\tif rErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"SearchBoardsForUser unable to replace unionSQL placeholders: %w\", rErr)\n\t\t}\n\t}\n\n\trows, err := s.mmDB.Query(unionSQL, unionArgs...)\n\tif err != nil {\n\t\ts.logger.Error(`searchBoardsForUser ERROR`, mlog.Err(err))\n\t\treturn nil, err\n\t}","sourceCodeStart":756,"sourceCodeEnd":792,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/store/mattermostauthlayer/mattermostauthlayer.go#L756-L792","documentation":"The final UNION query (boardMembersQ unioned with teamMembersSQL) failed ToSql() in SearchBoardsForUser. The combined prefix/suffix construction produced an invalid query that squirrel could not render.","triggerScenarios":"unionQ.ToSql() fails after union of boardMembersQ with the already-rendered teamMembersSQL via Prefix/Suffix — e.g. boardMembersQ itself was invalid, so combining propagates the failure.","commonSituations":"Same root causes as the earlier ToSql failures cascading into the union; edit mistakes in the Suffix SQL strings breaking placeholder/arg pairing.","solutions":["Fix the root ToSql error in boardMembersQ (or the earlier builders) first — the union inherits builder state.","Validate the Suffix SQL text and that args counts match '?' placeholders.","Test the union construction directly with a fixed set of inputs.","Check squirrel version for Prefix/Suffix with args regressions."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"boards, err := store.SearchBoardsForUser(userID, term)\nif err != nil {\n\tif strings.Contains(err.Error(), \"error getting unionSQL\") {\n\t\tlogger.Error(\"union query build failed in board search\", \"err\", err)\n\t\treturn nil, ErrInternalSearch\n\t}\n\treturn nil, err\n}","preventionTips":["Fix underlying builder errors first; union failures usually cascade.","Validate hand-written Prefix/Suffix SQL against placeholder counts.","Snapshot-test the full query rendering for the search feature."],"tags":["sql","squirrel","union-query","store"],"backgroundTag":"sql-build-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}