- Error number
- 206
- Severity
- 16 (user-correctable error)
- State
- 2
- Product
- Microsoft SQL Server Database Engine
- Versions
- All supported SQL Server versions (2016 to 2025), Azure SQL Database, Azure SQL Managed Instance
- Category
- Data Type & Conversion
- Last reviewed
- 24 October 2026
On this page
What it means
Error 206 means two values meet whose data types have no implicit conversion between them, such as an int sent to a date column, so SQL Server refuses to compile the statement.
Whenever a value is assigned, inserted, compared or combined with an operator, SQL Server needs both sides in one type. For most pairs it converts silently (int to decimal, varchar to date). For some pairs the conversion chart says no implicit conversion exists: int to date, int to uniqueidentifier, one table type to another. In those cases the batch stops with 206 at severity 16 and nothing runs. The message reads left to right as source is incompatible with target, so int is incompatible with date means an int was offered where a date is required.
Error 206 is about types, not values: it does not matter that 20261023 looks like a valid date. That is the difference from error 241 or error 245, which fire at run time when a conversion that is allowed meets a value it cannot read. The datetime2 trap is common after a migration: @d + 1 works on datetime but raises 206 on date, datetime2 and datetimeoffset.
Common causes
- An integer such as
20261023inserted into, or compared with, adateordatetime2column. - Date arithmetic with
+ 1or- 7ondate,datetime2ordatetimeoffset, which onlydatetimeandsmalldatetimesupport. - A numeric value sent to a
uniqueidentifiercolumn, often because the INSERT column list and the VALUES list are in different orders. - A table-valued parameter declared with a different table type than the procedure expects, even when both types have the same columns.
- A procedure parameter changed from int to date (or the reverse) while callers still pass the old type.
Diagnose it
Read-only These queries only read metadata and dynamic management views. They do not change data, permissions or configuration, so they are safe to run first.
Check the declared types of the target columns
SELECT c.name AS column_name, t.name AS data_type
FROM sys.columns AS c
JOIN sys.types AS t ON t.user_type_id = c.user_type_id
WHERE c.object_id = OBJECT_ID(N'dbo.Bookings')
ORDER BY c.column_id; The second type in the message (for example date) should match one of these columns. Compare it with the type of the value you send.
See the type of an expression without running it
sp_describe_first_result_set compiles a query and reports the type of each output column. Use it to confirm the replacement expression returns the type you expect.
EXEC sp_describe_first_result_set
N'SELECT DATEADD(day, 1, CAST(''2026-10-23T09:00'' AS datetime2)) AS next_day;'; system_type_name = datetime2(7). If you test the failing expression instead, the procedure reports the same error 206.
Find the table type a procedure parameter expects
SELECT p.name AS parameter_name,
SCHEMA_NAME(tt.schema_id) + N'.' + tt.name AS table_type,
p.is_readonly
FROM sys.parameters AS p
JOIN sys.table_types AS tt ON tt.user_type_id = p.user_type_id
WHERE p.object_id = OBJECT_ID(N'dbo.CancelOrders'); The exact table type to use when you declare the variable you pass. A different type name raises 206, even if its columns are identical.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Use DATEADD instead of + or - on dates
Read-onlyDATEADD works with every date and time type and states the unit explicitly, so the code keeps working if the column later changes from datetime to datetime2.
DECLARE @due datetime2 = '2026-10-23T09:00';
SELECT DATEADD(day, 1, @due) AS next_day;
Convert integer dates through text with style 112
Changes dataAn integer in yyyymmdd form has no direct path to date. Turn it into 8 characters first, then convert with style 112 (ISO yyyymmdd). Values that are not real dates still fail, with 241.
INSERT INTO dbo.Bookings (id, booked_on)
VALUES (1, CONVERT(date, CAST(20261023 AS char(8)), 112));
Declare the table variable with the procedure's own table type
Changes dataTable-valued parameters are matched by type name, not by shape. Declare the variable with the type shown by the third diagnostic and copy the rows across.
DECLARE @ids dbo.OrderIdList;
INSERT INTO @ids (order_id) VALUES (101), (102);
EXEC dbo.CancelOrders @ids = @ids;
Name the columns in every INSERT
Changes dataA column list in the same order as the VALUES list stops values landing in a column of an unrelated type, such as a user id in a uniqueidentifier column.
INSERT INTO dbo.Sessions (session_id, user_id)
VALUES (NEWID(), 42);
Examples
An integer date inserted into a date column
CREATE TABLE dbo.Bookings (id INT PRIMARY KEY, booked_on DATE);
INSERT INTO dbo.Bookings (id, booked_on) VALUES (1, 20261023); -- an int, not a date
Msg 206, Level 16, State 2, Line 3 Operand type clash: int is incompatible with date
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
Adding a day to a datetime2 with + 1
DECLARE @due datetime2 = '2026-10-23T09:00';
SELECT @due + 1 AS next_day; -- works for datetime, not for datetime2
Msg 206, Level 16, State 2, Line 2 Operand type clash: datetime2 is incompatible with int
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
A table-valued parameter with an identical but different type
CREATE TYPE dbo.OrderIdList AS TABLE (order_id INT);
CREATE TYPE dbo.IdList AS TABLE (order_id INT); -- same columns, different type
GO
CREATE PROCEDURE dbo.CancelOrders @ids dbo.OrderIdList READONLY
AS SELECT order_id FROM @ids;
GO
DECLARE @ids dbo.IdList;
EXEC dbo.CancelOrders @ids = @ids;
Msg 206, Level 16, State 2, Procedure dbo.CancelOrders, Line 0 Operand type clash: IdList is incompatible with OrderIdList
Reproduced on SQL Server 2025 (17.0.1145.4), 23 October 2026.
How to prevent it
Keep values in their real types end to end: dates as date or datetime2 parameters, identifiers as uniqueidentifier, and avoid integer or text stand-ins. Write date arithmetic with DATEADD and DATEDIFF from the start, so a later change from datetime to datetime2 does not break it.
Define each table type once and reuse it for every procedure that takes the same list. For which types convert implicitly and which never do, see SQL data types explained and the conversion chart in the CAST and CONVERT reference.
Common questions
Why does GETDATE() + 1 work but SYSDATETIME() + 1 fails with 206?
GETDATE() returns datetime, which supports adding a number of days. SYSDATETIME() returns datetime2, which does not. DATEADD(day, 1, SYSDATETIME()) works for both.
Will CAST fix an operand type clash?
Only if an explicit conversion exists. int to date has none, so CAST(20261023 AS date) fails too, with error 529. Convert through char(8) with style 112 instead.
My two table types have the same columns. Why are they incompatible?
SQL Server matches table-valued parameters by type, not by structure. A variable must be declared with exactly the type named in the procedure parameter.
Learn more on CodeWithSQL
Official documentation
- CAST and CONVERT (Transact-SQL)
- Data type conversion (Database Engine)
- Use table-valued parameters (Database Engine)
- Database Engine events and errors 0 to 999
Last technically reviewed 24 October 2026; examples and diagnostics run on SQL Server 2025 (17.0.1145.4). Message text checked against the engine's sys.messages catalogue.