Skip to content

Ledger table with computed column causes NRE during model validation #735

Description

  • SqlPackage or DacFx Version: 170.2.70
  • .NET Framework (Windows-only) or .NET Core: Both
  • Environment (local platform and source/target platforms): SQL Server 2022

Steps to Reproduce:

Add this to a project:

CREATE TABLE [dbo].[AccountTransactions] (
	[Id] [uniqueidentifier] NOT NULL,
	[GT] [bigint] NOT NULL,
	[Direction] [nvarchar](3) NOT NULL,
	[Quantity] [numeric](18, 3) NOT NULL,
	[SignedQuantity]  AS (case when [Direction]=N'OUT' then  -[Quantity] else [Quantity] end) PERSISTED
)
WITH (LEDGER = ON (APPEND_ONLY = ON, LEDGER_VIEW = dbo.AccountTransactions_LedgerView)); 

Build result in VS with classic .sqlproj:

C:\Program Files\Microsoft Visual Studio\18\Preview\MSBuild\Microsoft\VisualStudio\v18.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets(558,5): Error:  MSB4018: The "SqlBuildTask" task failed unexpectedly.
System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.Data.Tools.Schema.Sql.Validation.LedgerTableColumnUserDefinedTypeValidationRule.Analyze(SqlSchemaModel sqlSchemaModel, ISqlModelElement sqlElement, SqlRuleSetting ruleSetting, SqlRuleExecutionContext context)
   at Microsoft.Data.Tools.Schema.Sql.Validation.SqlValidationRule.Analyze(SqlRuleSetting ruleSetting, SqlRuleExecutionContext context)
   at Microsoft.Data.Tools.Schema.Sql.RuleEngine.SqlRuleEngine.ExecuteRuleImpl(SqlRuleSetting ruleSetting, SqlRuleExecutionContext context, Predicate`1 suppressProblem, IEnumerable`1& errors)
   at Microsoft.Data.Tools.Schema.Sql.RuleEngine.SqlRuleEngine.<>c__DisplayClass24_0.<RunRulesInParallel>b__0(Int32 i, ParallelLoopState loopState)
   at System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.b__1()
   at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
   at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object <p0>)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Parallel.ForWorker[TLocal](Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.For(Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`2 body)
   at Microsoft.Data.Tools.Schema.Sql.RuleEngine.SqlRuleEngine.RunRulesInParallel(IList`1 modelElements, List`1 elementsIndexesToRun, IEnumerable`1 ruleSettings, Predicate`1 suppressProblem, Dictionary`2 elementClassToRulesMap, List`1[] errorsArr, List`1[] problemsArr, Func`1 executeCanceled, Int32 maxDegreeOfParallelism)
   at Microsoft.Data.Tools.Schema.Sql.RuleEngine.SqlRuleEngine.ExecuteRules(IList`1 modelElements, IEnumerable`1 ruleSettings, IEnumerable`1& errors, Predicate`1 suppressProblem, Func`1 executeCanceled)
   at Microsoft.Data.Tools.Schema.Sql.RuleEngine.SqlRuleEngine.ExecuteRules(SqlSchemaModel dataSchemaModel, IEnumerable`1 ruleSettings, IEnumerable`1& errors, Predicate`1 suppressProblem, Func`1 executeCanceled)
   at Microsoft.Data.Tools.Schema.Sql.Build.SqlTaskHost.RunBuildValidation(SqlSchemaModel model, ErrorManager errorContainer, Func`1 buildCanceledQuery, HashSet`1 excludedRuleIDs)
   at Microsoft.Data.Tools.Schema.Sql.Build.SqlTaskHost.RunBuildValidations(ErrorManager errorManager)
   at Microsoft.Data.Tools.Schema.Tasks.Sql.TaskHostLoader.LoadImpl(ITaskHost providedHost, TaskLoggingHelper providedLogger)
   at Microsoft.Data.Tools.Schema.Tasks.Sql.TaskHostLoader.Load(ITaskHost providedHost, TaskLoggingHelper providedLogger)
   at Microsoft.Data.Tools.Schema.Tasks.Sql.SqlBuildTask.ExecuteLoadTaskHostStep()
   at Microsoft.Data.Tools.Schema.Tasks.Sql.SqlBuildTask.ExecuteStep(Func`1 step)
   at Microsoft.Data.Tools.Schema.Tasks.Sql.SqlBuildTask.ExecuteTask()
   at Microsoft.Data.Tools.Schema.Tasks.Sql.DataTask.Execute()
   at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
   at Microsoft.Build.BackEnd.TaskBuilder.d__26.MoveNext()
---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.Data.Tools.Schema.Sql.Validation.LedgerTableColumnUserDefinedTypeValidationRule.Analyze(SqlSchemaModel sqlSchemaModel, ISqlModelElement sqlElement, SqlRuleSetting ruleSetting, SqlRuleExecutionContext context)
   at Microsoft.Data.Tools.Schema.Sql.Validation.SqlValidationRule.Analyze(SqlRuleSetting ruleSetting, SqlRuleExecutionContext context)
   at Microsoft.Data.Tools.Schema.Sql.RuleEngine.SqlRuleEngine.ExecuteRuleImpl(SqlRuleSetting ruleSetting, SqlRuleExecutionContext context, Predicate`1 suppressProblem, IEnumerable`1& errors)
   at Microsoft.Data.Tools.Schema.Sql.RuleEngine.SqlRuleEngine.<>c__DisplayClass24_0.<RunRulesInParallel>b__0(Int32 i, ParallelLoopState loopState)
   at System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.b__1()
   at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
   at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object <p0>)<---

Done building project "Classic.sqlproj" -- FAILED.

Build FAILED.

Did this occur in prior versions? If not - which version(s) did it work in? No idea

(DacFx/SqlPackage/SSMS/Azure Data Studio)

Activity

ErikEJ commented on Jan 3, 2026

@ErikEJ
ContributorAuthor

This is the reverse engineered source of the failing rule, maybe column.TypeSpecifier is null in this case?

(Commenting out the computed column causes the build to pass)

 internal class LedgerTableColumnUserDefinedTypeValidationRule : SqlValidationRule
  {
    internal override RuleExecutionTime ExecutionTime => RuleExecutionTime.AtBuild;

    internal override IList<SqlRuleProblem> Analyze(
      SqlSchemaModel sqlSchemaModel,
      ISqlModelElement sqlElement,
      SqlRuleSetting ruleSetting,
      SqlRuleExecutionContext context)
    {
      if (sqlElement is SqlTable sqlTable && (sqlTable.LedgerType == SqlTableLedgerType.UpdatableLedgerTable || sqlTable.LedgerType == SqlTableLedgerType.AppendOnlyLedgerTable))
      {
        foreach (SqlColumn column in (IEnumerable<SqlColumn>) sqlTable.Columns)
        {
          if (column.TypeSpecifier.Type is SqlUserDefinedDataType)
            return (IList<SqlRuleProblem>) new List<SqlRuleProblem>()
            {
              (SqlRuleProblem) SqlValidationUtils.CreateValidationProblem((SqlValidationRule) this, sqlElement, SqlRuleProblemSeverity.Error, 71654, this.RuleProperties.Description, (object) SqlRuleEngineUtils.GetSchemaObjectName(sqlSchemaModel, (ISqlModelElement) column, ElementNameStyle.EscapedFullyQualifiedName))
            };
        }
      }
      return (IList<SqlRuleProblem>) new List<SqlRuleProblem>();
    }
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions