Skip to content

bundle plan reports a permanent, unconvergeable diff on apps.*.resources[].uc_securable.securable_kind (direct engine) #6342

Description

@geoffyip

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

  1. 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"
  1. databricks bundle deploy -t dev
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLICLI related issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions