-
Notifications
You must be signed in to change notification settings - Fork 42
Description
I recently upgraded our project from version 2.0.11 to version 4.5.0, and have experienced several errors running a large stored procedure with several table types and TVPs in play. We are using ODBC Driver 17 on Windows 10. The errors tend to read like this:
Error: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]The data for the table-valued parameter 6 doesn't conform to the table type of the parameter. SQL Server error is: 8169, state: 2
An example of this error is when we provide the following data:
[{
uuid: 'A2FF83F2-963F-4553-8837-D785E20707E3',
inspectionUuid: 'ECA07CC2-DF99-4868-999A-F14A2CC1A949',
identifierChecklistUuid: 'D274B030-A019-4C00-8396-01E53388E5FE',
inquiryId: '58BF1BE5-3FB7-4562-A239-27AFE621317C',
inspectionFindingId: '420B660C-B959-4B2B-90D9-55ACB657D94D',
parentFindingId: null,
deadline: '',
requirementsValue: '["58BF1BE5-3FB7-4562-A239-27AFE621317C"]',
classificationValue: '["2CA61A42-6F25-48E3-84EF-424692E3E1CC"]',
title: 'Specific Rights',
text: '<p>Violation</p><p></p><p></p>',
correctionRequired: 1,
findingAddedBy: 'Matt Hoffman',
findingAddedOn: '04/17/2025',
displayOrder: '0'
}]
to the following stored procedure segment:
USE [SansWrite X v10.0.6 Dev]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[saveInspection]
@options keyValuePairs READONLY,
@accountSettings accountSettings READONLY,
@inspectionAttachmentsData inspectionAttachmentsData READONLY,
@inspectionFindingCorrectionsData inspectionFindingCorrectionsData READONLY,
@inspectionFindingHistoryData inspectionFindingHistoryData READONLY,
@inspectionFindingsData inspectionFindingsData READONLY,
...
...
...
AS
BEGIN
SET XACT_ABORT ON
BEGIN TRANSACTION
SAVE TRANSACTION saveInspectionTransaction
BEGIN TRY
SET NOCOUNT ON;
...
...
...
insert into @existingInspectionFindingsDataUuids select uuid from inspectionFindingsData where inspectionUuid in ( select uuid from @inspectionUuids)
insert into @newUuids select uuid from @inspectionFindingsData where uuid not in (select uuid from @existingInspectionFindingsDataUuids)
update inspectionFindingsData
set uuid = s.uuid
,inspectionUuid = s.inspectionUuid
,identifierChecklistUuid = s.identifierChecklistUuid
,inquiryId = s.inquiryId
,inspectionFindingId = s.inspectionFindingId
,parentFindingId = s.parentFindingId
,deadline = s.deadline
,requirementsValue = s.requirementsValue
,classificationValue = s.classificationValue
,title = s.title
,text = s.text
,correctionRequired = s.correctionRequired
,findingAddedBy = s.findingAddedBy
,findingAddedOn = s.findingAddedOn
,displayOrder = s.displayOrder
,lastUpdated = CURRENT_TIMESTAMP
from @inspectionFindingsData s
inner join inspectionFindingsData t
on s.uuid = t.uuid
insert into inspectionFindingsData select *, CURRENT_TIMESTAMP from @inspectionFindingsData where uuid in (select uuid from @newUuids)
delete from @newUuids
...
...
...
COMMIT TRANSACTION
END TRY
BEGIN CATCH
THROW
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION saveInspectionTransaction
END
END CATCH
END
using the following user table type:
USE [SansWrite X v10.0.6 Dev]
GO
CREATE TYPE [dbo].[inspectionFindingsData] AS TABLE(
[uuid] [uniqueidentifier] NOT NULL,
[inspectionUuid] [uniqueidentifier] NOT NULL,
[identifierChecklistUuid] [uniqueidentifier] NOT NULL,
[inquiryId] [uniqueidentifier] NOT NULL,
[inspectionFindingId] [uniqueidentifier] NULL,
[parentFindingId] [uniqueidentifier] NULL,
[deadline] [varchar](50) NULL,
[requirementsValue] [varchar](max) NULL,
[classificationValue] [varchar](max) NULL,
[title] [varchar](max) NULL,
[text] [varchar](max) NULL,
[correctionRequired] [varchar](5) NULL,
[findingAddedBy] [varchar](100) NULL,
[findingAddedOn] [varchar](50) NULL,
[displayOrder] [int] NULL
)
GO
This specific example does not work with an array of length 1, but works once another item is added to the array. Unfortunately, a different table type conflict comes up for a different TVP in that case.
The data is converted to a TVP and added to the procedure using the following code:
const tableTypeForTvp = {...tableType};
tableTypeForTvp.addRowsFromObjects(data);
const tvp = sql.TvpFromTable(tableType);
tvps.push(tvp);
const pm = connection.procedureMgr();
pm.get(storedProcedureName, proc => {
proc.call(tvps, (err, results, output) => {
Despite the error seeming to originate from the ODBC Driver, the only modifications between a working version of this process and the version where we are seeing this error is a change from Node 14 to Node 22, and a change from msnodesqlv8 2.0.11 to 4.5.0. The data, table types, stored procedure, and driver have not been touched, outside of nullifying a single piece of data that seems to violate a length limit in TVPs.
Has there been a significant change to how TVPs and stored procedures are managed between these versions? If this behavior is intended, guidance on how to debug and resolve these errors would be appreciated.