Skip to content

sqlpackage /Action:Publish generates sp_addextendedproperty @level1type = N'NULL' (Msg 15600) for an extended property on a SECURITY POLICY #801

Description

@arnavrupde1

Summary

A .dacpac that contains an extended property on a Row-Level Security SECURITY POLICY cannot be published. sqlpackage /Action:Publish generates an sp_addextendedproperty call with @level1type = N'NULL', which the engine rejects with Msg 15600:

Msg 15600, Level 16, State 5, Procedure sp_addextendedproperty, Line 37
An invalid parameter or option was specified for procedure 'sp_addextendedproperty'.

The extended property is created on the source with @level1type = N'SECURITY POLICY' (the engine accepts this). Extract captures it correctly — the model element knows the host is a security policy:

<Element Type="SqlExtendedProperty" Name="[SqlSecurityPolicy].[dbo].[P].[BusinessPurpose]">

But on Publish, DacFx has no sp_addextendedproperty @level1type token for a security policy, so it emits the literal @level1type = N'NULL' and the deployment fails.

Steps to reproduce

1. Create the schema (any SQL Server 2016+ or Azure SQL Database):

CREATE TABLE dbo.T (Id INT PRIMARY KEY, TenantId INT);
GO
CREATE FUNCTION dbo.fn_pred(@TenantId INT)
RETURNS TABLE WITH SCHEMABINDING
AS RETURN SELECT 1 AS ok WHERE @TenantId = 1;
GO
CREATE SECURITY POLICY dbo.P
    ADD FILTER PREDICATE dbo.fn_pred(TenantId) ON dbo.T
    WITH (STATE = ON, SCHEMABINDING = ON);
GO
-- The trigger: an extended property on the security policy.
-- @level1type = N'SECURITY POLICY' is accepted by the engine.
EXEC sys.sp_addextendedproperty
    @name      = N'BusinessPurpose',
    @value     = N'demo extended property on a security policy',
    @level0type = N'SCHEMA', @level0name = 'dbo',
    @level1type = N'SECURITY POLICY', @level1name = 'P';
GO

2. Extract → succeeds (and captures the EP on the policy):

sqlpackage /Action:Extract \
  /SourceServerName:"<server>" \
  /SourceDatabaseName:"<db>" \
  /SourceUser:"<user>" \
  /SourcePassword:"<password>" \
  /TargetFile:/tmp/repro.dacpac
$ unzip -p /tmp/repro.dacpac model.xml | grep -i extendedpropert
        <Element Type="SqlExtendedProperty" Name="[SqlSecurityPolicy].[dbo].[P].[BusinessPurpose]">

3. Publish to a new empty database → FAILS:

sqlpackage /Action:Publish \
  /SourceFile:/tmp/repro.dacpac \
  /TargetServerName:"<server>" \
  /TargetDatabaseName:"<new-db>" \
  /TargetUser:"<user>" \
  /TargetPassword:"<password>"

Actual result

Updating database (Start)
Creating Table [dbo].[T]...
Creating Function [dbo].[fn_pred]...
Creating Security policy [dbo].[P]...
Creating Extended Property [dbo].[P].[BusinessPurpose]...
An error occurred while the batch was being executed.
Updating database (Failed)
*** Could not deploy package.
Error SQL72014: Core Microsoft SqlClient Data Provider: Msg 15600, Level 16, State 5, Procedure sp_addextendedproperty, Line 37 An invalid parameter or option was specified for procedure 'sp_addextendedproperty'.
Error SQL72045: Script execution error.  The executed script:
EXECUTE sp_addextendedproperty @name = N'BusinessPurpose', @value = N'demo extended property on a security policy', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'NULL', @level1name = N'P';

The generated script has @level1type = N'NULL' (the literal string NULL), which is not a valid sp_addextendedproperty level-1 type.

Expected result

Publish should emit @level1type = N'SECURITY POLICY' (the value the engine accepts and that was used to create the property), so the extended property round-trips. DacFx already records the host as SqlSecurityPolicy at extract time; the publish-side sp_addextendedproperty scripting just needs the matching level-1 type token.

Notes

  • The engine accepts EXEC sp_addextendedproperty ... @level1type = N'SECURITY POLICY' (with the space) directly; only the DacFx round-trip is broken.

Environment

  • sqlpackage version: 170.3.93.6
  • .NET runtime: 8.0.303
  • OS: Ubuntu 20.04.6 LTS (Linux 5.4.0-216-generic, x86_64)
  • Source / target: Azure SQL Database (also reproduces on SQL Server 2016+)
  • Action: Publish (of a .dacpac produced by Extract)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions