MetricSign
Start free
error-reference9 min·

Lakeflow Connect SQL Server: Why the Database Setup Step Keeps Failing

The setup wizard looks simple. Four steps, a few stored procedures, done. But the database setup step fails without telling you which prerequisite it actually checked and rejected.

Lees dit artikel in het Nederlands →

The setup wizard hides five distinct failure modes behind one error

Databricks community threads about Lakeflow Connect's SQL Server connector share a pattern: the database setup step fails, the error message says almost nothing useful, and the engineer spends hours toggling permissions that may not be the problem at all.

The setup step is doing real work behind the scenes. It verifies that the utility objects script has been installed correctly, checks that change tracking or CDC is enabled at both the database and table level, confirms the ingestion user has the right grants, and validates that DDL support objects exist for schema evolution. Any one of these checks can fail, but the wizard reports a single generic failure.

Here are the five causes, ordered by how often they appear in practice:

  1. The user who ran the utility script was not a member of db_owner, so the stored procedures installed incompletely or silently skipped permission grants.
  2. CDC capture instance slots are full — SQL Server allows a maximum of two per table, and if both are occupied by non-Lakeflow instances, the connector cannot create its lakeflow_ prefixed instance.
  3. The ingestion user is missing SELECT on sys.change_tracking_tables, sys.change_tracking_databases, or the cdc schema.
  4. The utility script version is outdated — the current version is 1.5, and older versions use a different capture instance prefix (New_ instead of lakeflow_) that the latest gateway does not recognize.
  5. Change tracking or CDC is enabled at the database level but not on the specific tables you selected for ingestion.

Each of these requires a different fix. The rest of this post walks through how to confirm which one you hit.

db_owner is required for setup, not for ingestion — and that distinction breaks people

The Databricks documentation states clearly that the user running the utility objects script must be a member of db_owner. But it also says the ingestion user only needs specific SELECT grants. Engineers read this as "my ingestion user does not need db_owner" — which is correct — and then run the utility script as the ingestion user. The script does not hard-fail. It installs some objects, silently skips others, and the setup step later rejects the incomplete installation.

To verify, connect as a user with db_owner and run:

SELECT dbo.lakeflowUtilityVersion_1_5() AS UtilityVersion;
SELECT dbo.lakeflowDetectPlatform() AS Platform;

If either function does not exist, the script did not complete. To grant db_owner to your setup user on modern SQL Server (2012+):

USE [your_database];
ALTER ROLE db_owner ADD MEMBER [your_setup_user];
GO

On legacy instances or restricted environments, use sp_addrolemember instead:

USE [your_database];
EXEC sp_addrolemember 'db_owner', 'your_setup_user';
GO

After granting the role, re-run the entire utility_script.sql. Do not assume partial installation is recoverable — the script is designed to be idempotent, so a clean re-run is safer than trying to patch individual objects. Once the script completes, run the verification functions again. Both should return values without errors.

A common variation of this problem appears on Azure SQL Database, where the setup user needs membership in the ##MS_DatabaseConnector## server role rather than individual master database grants. If you are on Azure SQL Managed Instance, you need VIEW ANY DATABASE at the server level plus explicit master database access. The platform matters.

Lakeflow Connect SQL Server Pre-Flight Checklist 1 Confirm utility script v1.5 installed: SELECT dbo.lakeflowUtilityVersi 2 Verify setup user has db_owner role on target database 3 Check database-level change tracking or CDC is enabled 4 Verify table-level CT/CDC activation for all target tables 5 Confirm CDC capture instance slots available (max 2 per table) 6 Run lakeflowFixPermissions with @User parameter set 7 Verify SQL Server Agent is running (on-premises/RDS only) 8 Test ingestion user can SELECT from cdc schema and sys.change_tracking
Lakeflow Connect SQL Server Pre-Flight Checklist

CDC capture instance slots fill up silently

SQL Server enforces a hard limit of two capture instances per table. Lakeflow Connect needs at least one available slot to create its lakeflow__

_1 instance. If both slots are occupied by existing capture instances from other systems — an older replication setup, a homegrown CDC consumer, or a previous Lakeflow installation using the deprecated New_ prefix — the connector cannot proceed.

This failure is particularly frustrating because CDC appears to be enabled. The database-level check passes. The table-level check passes. But the connector cannot create its own capture instance, and the setup step fails.

To check capture instance usage per table:

SELECT
    SCHEMA_NAME(t.schema_id) + '.' + t.name AS TableName,
    ct.capture_instance,
    ct.start_lsn,
    ct.create_date
FROM cdc.change_tables ct
INNER JOIN sys.tables t ON ct.source_object_id = t.object_id;

If any table shows two capture instances and neither starts with lakeflow_, you have found the problem. Your options: remove one of the existing capture instances if it is no longer needed, or switch that table to change tracking instead of CDC. Change tracking works for any table with a primary key, uses less overhead on the source, and does not have the two-instance limit.

If you are upgrading from an older utility script version, you may see capture instances prefixed with New_ instead of lakeflow_. Running the latest utility_script.sql (version 1.5) handles this migration automatically, but only if a capture instance slot is available for the new naming convention during the transition. Stop the gateway before upgrading — the script replaces DDL support objects, and a running pipeline will lose DDL audit events during the swap.

The hybrid approach Databricks recommends — change tracking for tables with primary keys, CDC for tables without — sidesteps the slot problem entirely for most schemas.

The ingestion user's permission surface is larger than it looks

Even after the utility script runs successfully, the ingestion user can still lack permissions that cause the setup step to fail. The required grants span three categories: system catalog access, change detection access, and table-level SELECT.

For system catalog access, the ingestion user needs SELECT on sys.databases, sys.schemas, sys.tables, sys.columns, sys.key_constraints, sys.foreign_keys, sys.check_constraints, sys.default_constraints, sys.change_tracking_tables, sys.change_tracking_databases, sys.objects, sys.triggers, sys.indexes, and sys.index_columns. It also needs EXECUTE on sp_tables, sp_columns_100, sp_pkeys, and sp_statistics_100, plus VIEW DATABASE PERFORMANCE STATE.

For CDC specifically, the user needs SELECT on the entire cdc schema. On on-premises and RDS instances, it also needs VIEW SERVER STATE to query sys.dm_server_services, which Lakeflow uses to verify SQL Server Agent is running. If Agent is stopped, CDC changes do not get captured, and the connector will refuse to proceed.

The utility script's lakeflowSetupChangeTracking and lakeflowSetupChangeDataCapture procedures grant CDC and CT-specific permissions automatically, but only if the @User parameter is set. If you ran the procedures without specifying @User, the permissions were not granted. Run lakeflowFixPermissions to fill the gap:

EXEC dbo.lakeflowFixPermissions
    @User = 'your_ingestion_user',
    @Tables = 'ALL';

This grants system-level and table-level SELECT permissions. It is safe to run repeatedly — the procedure is idempotent. After running it, verify the setup step again. If you are targeting specific schemas rather than all tables, replace 'ALL' with 'SCHEMAS:Sales,HR' or a comma-separated table list to follow least-privilege principles.

Change detection enabled at the database level means nothing without table-level activation

This is the most common false confidence. An engineer enables change tracking at the database level and assumes tables inherit it. They do not. Change tracking must be explicitly enabled on each table, and CDC must be explicitly enabled with a capture instance per table.

To check database-level change tracking:

SELECT
    d.name AS DatabaseName,
    ctd.is_auto_cleanup_on,
    ctd.retention_period,
    ctd.retention_period_units_desc
FROM sys.change_tracking_databases ctd
INNER JOIN sys.databases d ON ctd.database_id = d.database_id
WHERE d.name = DB_NAME();

To check which tables actually have change tracking enabled:

SELECT
    SCHEMA_NAME(t.schema_id) + '.' + t.name AS TableName,
    ct.is_track_columns_updated_on,
    ct.begin_version,
    ct.cleanup_version
FROM sys.change_tracking_tables ct
INNER JOIN sys.tables t ON ct.object_id = t.object_id;

If your target tables are missing from this result set, the setup step will fail regardless of database-level configuration. The fix is straightforward — re-run the setup procedure with the correct table list:

EXEC dbo.lakeflowSetupChangeTracking
    @Tables = 'Sales.Orders,Production.Products',
    @User = 'your_ingestion_user',
    @Retention = '2 DAYS';

The @Retention parameter controls how long change tracking history is preserved before auto-cleanup removes it. Two days is the Databricks recommendation for most workloads, but if your ingestion pipeline runs infrequently or experiences extended downtime, increase it. If the retention window expires before the pipeline reads the changes, Lakeflow triggers a full refresh of that table — an expensive operation on large datasets that also resets downstream watermarks.

For CDC, check table-level enablement by querying cdc.change_tables. If a table has is_cdc_enabled = 1 at the database level but no entry in cdc.change_tables, the capture instance was never created. Run lakeflowSetupChangeDataCapture targeting those specific tables.

Run the verification queries before the wizard, not after it fails

The setup wizard's error messages are improving with each Databricks runtime release, but as of early 2026 they still collapse multiple failure modes into generic messages. The most reliable approach is to run the full verification suite before attempting the setup step.

A pre-flight checklist in SQL:

-- 1. Confirm utility script version
SELECT dbo.lakeflowUtilityVersion_1_5() AS UtilityVersion;

-- 2. Confirm platform detection
SELECT dbo.lakeflowDetectPlatform() AS Platform;

-- 3. Confirm database-level CT
SELECT * FROM sys.change_tracking_databases
WHERE database_id = DB_ID();

-- 4. Confirm table-level CT
SELECT SCHEMA_NAME(t.schema_id) + '.' + t.name
FROM sys.change_tracking_tables ct
JOIN sys.tables t ON ct.object_id = t.object_id;

-- 5. Confirm CDC database-level
SELECT is_cdc_enabled FROM sys.databases
WHERE database_id = DB_ID();

-- 6. Confirm CDC capture instances
SELECT capture_instance FROM cdc.change_tables;

-- 7. Confirm ingestion user permissions
EXEC dbo.lakeflowFixPermissions
    @User = 'your_ingestion_user',
    @Tables = 'ALL';

If every query returns expected results and lakeflowFixPermissions completes without error, the setup step should pass. If it still fails, check the gateway cluster driver logs — download them from the pipeline details page and search for INGESTION_GATEWAY_CONNECTION_ERROR or INGESTION_GATEWAY_INTERNAL_ERROR. The former points to network-level issues (firewall rules, incorrect hostname or port), while the latter requires log-level inspection for stack traces.

For teams running multiple Lakeflow Connect pipelines across different SQL Server instances, MetricSign groups ingestion failures by root cause — distinguishing permission errors from connectivity timeouts from CDC configuration gaps — so the on-call engineer sees one incident per underlying problem rather than one alert per failed pipeline. This matters when a single Active Directory password rotation breaks ingestion across twelve databases simultaneously.

Frequently asked questions

Why does the Lakeflow Connect database setup step fail even though CDC is enabled?+
CDC enabled at the database level does not automatically enable it on individual tables. Each table needs an explicit capture instance created via lakeflowSetupChangeDataCapture. Additionally, the ingestion user needs SELECT on the cdc schema, and on-premises or RDS instances require VIEW SERVER STATE to verify SQL Server Agent status. Run the verification queries against cdc.change_tables to confirm table-level enablement.
Do I need db_owner for the Lakeflow Connect ingestion user?+
No. db_owner is only required for the user who runs the utility objects script (utility_script.sql). The ingestion user needs specific SELECT grants on system catalog views, the cdc schema (if using CDC), and target tables. The lakeflowFixPermissions stored procedure grants these automatically when called with the @User parameter.
What happens when both CDC capture instance slots are occupied on a table?+
SQL Server allows a maximum of two capture instances per table. If both slots are taken by non-Lakeflow instances, the connector cannot create its lakeflow_ prefixed instance and the setup step fails. Either remove an unused capture instance or switch that table to change tracking instead of CDC. Change tracking has no similar slot limitation.
How do I upgrade from an older Lakeflow utility script version?+
Stop the gateway first, then re-run the latest utility_script.sql (v1.5) as a db_owner user. The script removes previous versioned objects and installs new ones. After installation, re-run lakeflowSetupChangeTracking and lakeflowSetupChangeDataCapture with your original parameters. The upgrade migrates the old New_ capture instance prefix to the new lakeflow_ prefix automatically.

Related integrations