Troubleshooting Guide: SQL Server Error 9980 — “Variable parameters cannot be passed to fulltext predicates: contains”
Why This Error Happens
This error occurs because SQL Server’s full-text search engine (CONTAINS/FREETEXT predicates) requires the search string to be resolved at parse/compile time, not at execution time. When a Transact-SQL variable is passed directly as the search condition inside a CONTAINS predicate, the query optimizer cannot statically validate or optimize the full-text expression, triggering Error 9980. This typically happens in stored procedures, parameterized queries, or dynamically generated T-SQL where developers attempt to pass @variable directly into CONTAINS(column, @variable) instead of using dynamic SQL or parameterized full-text constructs correctly.
Step-by-Step Resolution Guide
Step 1: Identify the Offending Query
- Locate the stored procedure, function, or ad-hoc query throwing Error 9980.
- Check SQL Server Management Studio (SSMS) error details or the Windows Event Viewer under Applications and Services Logs > MSSQLSERVER for the exact line number.
- Confirm the query uses a pattern like
WHERE CONTAINS(column_name, @searchVariable).
Step 2: Convert to Dynamic SQL Execution
- Rewrite the static query to use
sp_executesqlso the variable is injected into the SQL string before execution, rather than passed as a native parameter to CONTAINS. - Example fix:
DECLARE @sql NVARCHAR(MAX);
DECLARE @searchTerm NVARCHAR(100) = '"server*"';
SET @sql = N'SELECT * FROM Documents WHERE CONTAINS(ContentColumn, @term)';
EXEC sp_executesql @sql, N'@term NVARCHAR(100)', @term = @searchTerm;
- Note:
sp_executesqldoes support parameterization for CONTAINS, unlike inline variable substitution — this is the officially supported workaround from Microsoft.
Step 3: Validate Full-Text Catalog and Index Health
- Run the following to ensure the underlying full-text catalog is not corrupted, which can sometimes mask as predicate errors:
SELECT * FROM sys.fulltext_catalogs;
SELECT * FROM sys.dm_fts_index_population;
- If the catalog shows a “FAILED” or “PAUSED” status, rebuild it:
ALTER FULLTEXT CATALOG YourCatalogName REBUILD;
Step 4: Update SQL Server 2025 Cumulative Update
- Open SQL Server Configuration Manager on Windows Server 2025 / Windows 11 and verify the current build number.
- Navigate to
C:\Program Files\Microsoft SQL Server\MSSQL17.MSSQLSERVER\MSSQL\Log\ERRORLOGto check the version string. - Apply the latest Cumulative Update (CU) from Microsoft, as early 2025 builds had known regressions with full-text predicate parameter binding.
Alternative or Verification Steps
- Verify the Fix: Re-run the stored procedure or query using
sp_executesqlwith a sample parameter value and confirm Error 9980 no longer appears in SSMS or the SQL Server log. - Alternative Workaround: If
sp_executesqlis not feasible due to application architecture, useCONTAINSTABLE()in a derived table/JOIN instead of embedding CONTAINS directly in the WHERE clause, as CONTAINSTABLE often handles parameterized inputs more flexibly in legacy codebases.