mattermost-community/focalboard · error
SearchBoardsForUserInTeam unable to replace unionSQL placeho
Error message
SearchBoardsForUserInTeam unable to replace unionSQL placeholders: %w
What it means
In SearchBoardsForUserInTeam, sq.Dollar.ReplacePlaceholders failed converting '?' placeholders to '$N' for Postgres/SQLite on the final union SQL. Pure string-rewrite failure over the rendered query, indicating malformed rendered SQL.
Source
Thrown at server/services/store/mattermostauthlayer/mattermostauthlayer.go:882
unionQ := openBoardsQ.
Prefix("(").
Suffix(") UNION ("+memberBoardsSQL, memberBoardsArgs...).
Suffix(") UNION ("+channelMemberBoardsSQL+")", channelMemberBoardsArgs...)
unionSQL, unionArgs, err := unionQ.ToSql()
if err != nil {
return nil, fmt.Errorf("SearchBoardsForUserInTeam error getting unionSQL: %w", err)
}
// if we're using postgres or sqlite, we need to replace the
// question mark placeholder with the numbered dollar one, now
// that the full query is built
if s.dbType == model.PostgresDBType || s.dbType == model.SqliteDBType {
var rErr error
unionSQL, rErr = sq.Dollar.ReplacePlaceholders(unionSQL)
if rErr != nil {
return nil, fmt.Errorf("SearchBoardsForUserInTeam unable to replace unionSQL placeholders: %w", rErr)
}
}
rows, err := s.mmDB.Query(unionSQL, unionArgs...)
if err != nil {
s.logger.Error(`searchBoardsForUserInTeam ERROR`, mlog.Err(err))
return nil, err
}
defer s.CloseRows(rows)
return s.boardsFromRows(rows, false)
}
func (s *MattermostAuthLayer) boardsFromRows(rows *sql.Rows, removeDuplicates bool) ([]*model.Board, error) {
boards := []*model.Board{}
idMap := make(map[string]struct{})
for rows.Next() {View on GitHub (pinned to a84bbb65e3)
Solutions
- Log unionSQL on failure and scan for non-placeholder '?' characters.
- Escape literal '?' in any hand-written SQL fragments.
- Upgrade the squirrel dependency.
- Verify s.dbType detection so the rewrite branch only runs for postgres/sqlite.
Defensive patterns
Strategy: try-catch
Try / catch
boards, err := store.GetBoardsForUserAndTeam(userID, teamID, term)
if err != nil {
if strings.Contains(err.Error(), "unable to replace unionSQL placeholders") {
logger.Error("$N placeholder rewrite failed; check literal '?' in SQL", "err", err)
return nil, ErrInternalSearch
}
return nil, err
} Prevention
- Escape literal '?' in hand-written SQL fragments.
- Run CI queries against postgres and sqlite dialects.
- Keep squirrel current and dbType detection verified.
When it happens
Trigger: s.dbType is postgres or sqlite and the union SQL string can't be placeholder-rewritten — malformed '?' usage or broken SQL text from the union build.
Common situations: Literal '?' characters in injected SQL fragments; corrupted union SQL from build bugs; old squirrel versions; wrong dbType detection.
Related errors
- SearchBoardsForUser unable to replace unionSQL placeholders:
- getBlockHistoryNewestChildren unable to replace sql placehol
- SearchBoardsForUser error getting teamMembersSQL: %w
- SearchBoardsForUser error getting channelMembersSQL: %w
- SearchBoardsForUser error getting unionSQL: %w
AI-assisted analysis of mattermost-community/focalboard@a84bbb65e3 (2026-08-30).
Data as JSON: /api/errors/ab0e39945d505a8e.
Report an issue: GitHub.