CLI version: v1.13.0 (latest at time of filing, released 2026-08-20)
Engine: direct (bundle.engine: direct)
Cloud: Azure Databricks
Summary
securable_kind is a server-populated field on app uc_securable resources.
It is absent from the bundle schema, so it cannot be declared, and it is not
tagged output-only in the plan differ, so bundle plan reports it as a change
on every run. The diff can never converge: a deploy rewrites the entries and
the server recomputes the field again.
Reproduce
- Declare a Databricks App in a bundle with one or more TABLE
uc_securable resources:
resources:
apps:
my_app:
name: "my-app"
source_code_path: ../app
resources:
- name: "my-table"
uc_securable:
securable_full_name: my_catalog.my_schema.my_table
securable_type: "TABLE"
permission: "SELECT"
databricks bundle deploy -t dev
databricks bundle plan -t dev -o json
Expected: resources.apps.my_app -> skip (nothing changed).
Actual: resources.apps.my_app -> update, with one change per TABLE
securable:
"resources[6].uc_securable.securable_kind": { "action": "update", "remote": "TABLE_DELTA" },
"resources[5].uc_securable.securable_kind": { "action": "update", "remote": "TABLE_ONLINE_VECTOR_INDEX_DIRECT" }
In our bundle this was 13 entries, on every plan, indefinitely.
Why it cannot be worked around in config
- It cannot be declared.
databricks bundle schema (v1.13.0) defines
apps.AppResourceUcSecurable with exactly permission,
securable_full_name, securable_type, and additionalProperties: false.
Adding securable_kind fails bundle validate.
- Its values are not expressible anyway.
TABLE_DELTA and
TABLE_ONLINE_VECTOR_INDEX_DIRECT are a finer taxonomy than the declarable
securable_type enum (VOLUME | TABLE | FUNCTION | CONNECTION).
- There is no
ignore_changes. The direct engine documents only
lifecycle.started, and for apps/clusters/sql_warehouses.
- VOLUME securables are unaffected — they carry no
securable_kind, and
a VOLUME entry in the same list plans clean. Only TABLE entries drift.
Suggested fix
Tag securable_kind output-only in the plan differ. ~20 sibling fields in the
same plan entry already are, e.g.:
"id": { "action": "skip", "reason": "spec:output_only" },
"url": { "action": "skip", "reason": "spec:output_only" },
"app_status": { "action": "skip", "reason": "spec:output_only" },
"service_principal_id": { "action": "skip", "reason": "spec:output_only" }
securable_kind appears to have been missed rather than deliberately included.
The v1.13.0 notes already list phantom-diff fixes for webhook_notifications,
empty grants lists and input-only fields, so this class is known.
Impact
A permanently dirty plan defeats the purpose of plan as a pre-deploy gate:
reviewers stop reading a diff that always has the same 13 lines in it, which is
exactly when a real destructive change slips through. We ultimately had to
delete every TABLE uc_securable from the app and replace them with UC grants
to get a clean plan — losing the bundle's record of those grants.
Second observation — possibly related, possibly its own issue
While working around the above, bundle deploy failed on the app resource:
Error: cannot update resources.apps.advance-notice-app: updating id=advance-notice-app:
failed to reach SUCCEEDED, got FAILED: Unexpectedly failed to update app's compute size.
Please try again later.
The same plan reported compute_size as
{"action":"skip","reason":"backend_default","remote":"MEDIUM"} — i.e. the CLI
was not changing compute size, yet the update failed on it. The app itself
was unaffected (RUNNING, MEDIUM, prior deployment intact), but the deploy
aborted and took an unrelated job change with it.
Declaring compute_size: MEDIUM explicitly (matching the live value, so a
no-op) has been followed by three successful deploys. That is suggestive, not
proof — the error text says "try again later", so it may simply be transient.
Worth checking whether the app update path sends a payload that omits
compute_size when it is undeclared, causing the backend to attempt a reset.
CLI version: v1.13.0 (latest at time of filing, released 2026-08-20)
Engine:
direct(bundle.engine: direct)Cloud: Azure Databricks
Summary
securable_kindis a server-populated field on appuc_securableresources.It is absent from the bundle schema, so it cannot be declared, and it is not
tagged output-only in the plan differ, so
bundle planreports it as a changeon every run. The diff can never converge: a deploy rewrites the entries and
the server recomputes the field again.
Reproduce
uc_securableresources:databricks bundle deploy -t devdatabricks bundle plan -t dev -o jsonExpected:
resources.apps.my_app -> skip(nothing changed).Actual:
resources.apps.my_app -> update, with one change per TABLEsecurable:
In our bundle this was 13 entries, on every plan, indefinitely.
Why it cannot be worked around in config
databricks bundle schema(v1.13.0) definesapps.AppResourceUcSecurablewith exactlypermission,securable_full_name,securable_type, andadditionalProperties: false.Adding
securable_kindfailsbundle validate.TABLE_DELTAandTABLE_ONLINE_VECTOR_INDEX_DIRECTare a finer taxonomy than the declarablesecurable_typeenum (VOLUME | TABLE | FUNCTION | CONNECTION).ignore_changes. The direct engine documents onlylifecycle.started, and for apps/clusters/sql_warehouses.securable_kind, anda
VOLUMEentry in the same list plans clean. Only TABLE entries drift.Suggested fix
Tag
securable_kindoutput-only in the plan differ. ~20 sibling fields in thesame plan entry already are, e.g.:
securable_kindappears to have been missed rather than deliberately included.The v1.13.0 notes already list phantom-diff fixes for
webhook_notifications,empty grants lists and input-only fields, so this class is known.
Impact
A permanently dirty plan defeats the purpose of
planas a pre-deploy gate:reviewers stop reading a diff that always has the same 13 lines in it, which is
exactly when a real destructive change slips through. We ultimately had to
delete every TABLE
uc_securablefrom the app and replace them with UC grantsto get a clean plan — losing the bundle's record of those grants.
Second observation — possibly related, possibly its own issue
While working around the above,
bundle deployfailed on the app resource:The same plan reported
compute_sizeas{"action":"skip","reason":"backend_default","remote":"MEDIUM"}— i.e. the CLIwas not changing compute size, yet the update failed on it. The app itself
was unaffected (
RUNNING,MEDIUM, prior deployment intact), but the deployaborted and took an unrelated job change with it.
Declaring
compute_size: MEDIUMexplicitly (matching the live value, so ano-op) has been followed by three successful deploys. That is suggestive, not
proof — the error text says "try again later", so it may simply be transient.
Worth checking whether the app update path sends a payload that omits
compute_sizewhen it is undeclared, causing the backend to attempt a reset.