Databricks streaming guardian
Guard production Databricks data pipelines — Delta Lake, Liquid Clustering, Structured Streaming, Auto Loader, and DLT — against the twelve foot-guns that fire at scale: OPTIMIZE/auto-compaction conflicts, Liquid-Clustering merge conflicts, VACUUM breaking a streaming checkpoint, RocksDB OOM, Auto Loader schema-evolution stops, and DLT refresh data loss. Includes a PreToolUse hook that blocks DROP/CREATE-OR-REPLACE/VACUUM on a table with active streaming consumers. Use when a Delta MERGE/OPTIMIZE fails with a concurrency exception, a stream breaks after VACUUM or a table replace, an Auto Loader stream stops on a new column, a DLT refresh drops data, or before running a destructive op on a streamed-from table. Trigger with "ConcurrentAppendException", "ConcurrentDeleteDeleteException", "DELTA_FILE_NOT_FOUND", "streaming checkpoint broke", "vacuum broke my stream", "autoloader UnknownFieldException", "dlt full refresh".From its SKILL.md
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill databricks-streaming-guardianAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
14.0 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
Databricks Streaming Guardian
The data-ops spine of the pack. Delta Lake, Liquid Clustering, Structured Streaming, and DLT each ship a different set of foot-guns that fire most visibly when production data flows through them at scale — and most of them are documented platform decisions that surprise engineers, not bugs. This skill's job is friction at trigger time (a hook that blocks the genuinely-irreversible op) plus deterministic recovery when something already broke.
Overview
Twelve foot-guns, grouped by the surface that triggers them. Eleven are owned
outright (D01–D10, D12); the twelfth — D11, DLT rebuild cost — is shared with
databricks-cost-leak-hunter: this skill checks the rebuild cost as part of
pre-refresh safety, that skill owns ongoing cost optimization.
Delta write conflicts. D01 ConcurrentDeleteDeleteException — a manual
OPTIMIZE colliding with auto-compaction, which is silently enabled on any table
touched by MERGE/UPDATE/DELETE. D02 ConcurrentAppendException after moving
to Liquid Clustering — LC keeps file-set-level writer conflicts; a fan-out MERGE
breaks unless its predicate is narrowed to the clustering keys.
Streaming + checkpoint. D03 DELTA_FILE_NOT_FOUND_DETAILED — VACUUM deletes
files the checkpoint pins to. D04 silent checkpoint corruption / reset to batch 0.
D05 RocksDB state-store off-heap OOM (the heap looks fine while off-heap state pins
multi-GB). D12 DIFFERENT_DELTA_TABLE_READ_BY_STREAMING_SOURCE — CREATE OR REPLACE mints a new UUID and kills every active consumer.
Migration + evolution. D06 Liquid-Clustering migration's hidden full-rewrite
cost + downstream partition-predicate breakage. D07 time travel breaking silently
when VACUUM crosses the retention boundary. D10 Auto Loader
UnknownFieldException stopping the stream on every new column.
DLT. D08 the @dlt.table thread race (out-of-order registration). D09 full
refresh silently dropping data from a non-replayable source. D11 the rebuild cost
multiplier (checked before a full refresh; ongoing DLT cost is
databricks-cost-leak-hunter's job).
The hook (AP02/AP06 — this pack's only blocking hook). A PreToolUse hook
(hooks/streaming-guard-hook.py) intercepts a Bash command that runs DROP TABLE,
CREATE OR REPLACE TABLE, or VACUUM against a table and — only when it confirms
via system.streaming.query_progress that an active stream reads that table —
blocks it with a message naming the consumers and the pain. It is precise by
design: it matches only real SQL-execution surfaces (never a git commit mentioning
"drop table"), and it fails open — if it cannot verify consumers, it allows
rather than false-block. Blocking is reserved for the genuinely irreversible.
Deterministic work lives in scripts/; deep knowledge in references/; the
Liquid-Clustering predicate rewrite in the merge-rewriter subagent. Two data
planes: the databricks-workspace-mcp control plane (cluster/pipeline events) and
the CLI Statement Execution API for system.* reads. Either absent → advisory mode
on pasted input.
Prerequisites
databricks-workspace-mcpregistered — forclusters_events(RocksDB OOM correlation) andpipelines_get(DLT event log). Absent → advisory mode.- Databricks CLI authenticated +
jq, andDATABRICKS_WAREHOUSE_IDset — for thesystem.streaming.query_progressreads the hook and recovery flows use. The hook fails open (allows) if these are absent, so it never false-blocks. - The hook is a plugin-level
PreToolUsehook — it runs on Bash commands once the pack is installed. It is silent on everything except a confirmed-unsafe destructive op.
Instructions
Pick the flow by symptom. Always name the exact, searchable Databricks error
string — ConcurrentAppendException, ConcurrentDeleteDeleteException,
DELTA_FILE_NOT_FOUND_DETAILED, DIFFERENT_DELTA_TABLE_READ_BY_STREAMING_SOURCE,
UnknownFieldException — even when the user paraphrases it or gives a short form;
the full code is what an operator greps logs and docs for.
Step 1: Before a destructive op (the hook does this automatically)
Running DROP TABLE / CREATE OR REPLACE TABLE / VACUUM on a table? The hook
checks for active streaming consumers first and blocks if any exist. To check
manually, query system.streaming.query_progress for a stream whose
source_description names the table. If consumers exist: do NOT CREATE OR REPLACE (use ALTER/in-place — D12) and do NOT VACUUM below the consumers'
checkpoint lag (D03/D07). See
${CLAUDE_SKILL_DIR}/references/checkpoint-recovery.md.
Step 2: A Delta write conflict (D01, D02)
-
ConcurrentDeleteDeleteException(D01) — before a manualOPTIMIZE, probe the table for auto-compaction:bash "${CLAUDE_SKILL_DIR}/scripts/pre-optimize-check.sh" --table main.sales.ordersIf it reports COLLISION RISK, don't run manual
OPTIMIZE(or disable auto-compaction first). Details:${CLAUDE_SKILL_DIR}/references/concurrency-conflicts.md. -
ConcurrentAppendExceptionon a Liquid-Clustering table (D02) — hand the failingMERGEto themerge-rewritersubagent; it fetches the target's clustering keys viaDESCRIBE DETAILand narrows theONpredicate so writers touch disjoint file sets.
Step 3: A broken streaming source (D03, D04, D12)
Map the symptom to the failure class and its exact error code, then get the recovery tier from the decision tree:
file-not-found→DELTA_FILE_NOT_FOUND_DETAILED(VACUUM deleted pinned files — D03)uuid-changed→DIFFERENT_DELTA_TABLE_READ_BY_STREAMING_SOURCE(CREATE OR REPLACE minted a new UUID — D12)checkpoint-reset→ silent batchId regression / checkpoint corruption (D04)transient→ a restartable blip with an intact checkpoint
python3 "${CLAUDE_SKILL_DIR}/scripts/recover-streaming-source.py" \
--failure file-not-found --time-travel yes # or uuid-changed / checkpoint-reset / transient
It echoes the canonical error code and recommends SAFE_RESTART /
REPROCESS_FROM_OFFSET / RESTORE_FROM_TIME_TRAVEL / FULL_RESET_BACKFILL with the
data-loss tradeoff stated up front. Name that full code in your answer — not just
the short class. The full
three-tier reasoning is in
${CLAUDE_SKILL_DIR}/references/checkpoint-recovery.md.
Step 4: RocksDB state-store OOM (D05)
A driver/executor OOM while the JVM heap looks healthy points at off-heap RocksDB
state. Correlate the OOM to state size with clusters_events, then bound the
memory and enable changelog checkpointing per
${CLAUDE_SKILL_DIR}/references/rocksdb-state-store-tuning.md.
Step 5: Auto Loader schema evolution (D10)
A stream stopping with UnknownFieldException on a new column is the default
addNewColumns mode. Choose the mode deliberately (evolve-and-restart vs
rescue's silent widening) and pin types with schemaHints per
${CLAUDE_SKILL_DIR}/references/autoloader-schema-evolution.md.
Step 6: DLT rebuild safety (D08, D09, D11)
Before a DLT full refresh, confirm every source is replayable (a Kafka topic past
retention or a truncate-and-load source loses data on refresh — D09) and that
@dlt.table registration is deterministic (the thread race — D08). Read the DLT
event log with pipelines_get; the checklist is in
${CLAUDE_SKILL_DIR}/references/dlt-rebuild-safety.md.
Output
- A hook decision — a destructive op on a streamed-from table is blocked with the active consumers named and the pain (D12 / D03-D07) explained; everything else passes silently.
- A pre-OPTIMIZE verdict — SAFE or COLLISION RISK (auto-compaction on) with the disable-or-serialize fix.
- A rewritten MERGE — the LC clustering-key-scoped predicate (from
merge-rewriter) that stopsConcurrentAppendException. - A recovery recommendation — the recovery tier + steps + the data-loss risk, for the specific failure class.
- A tuning / mode / refresh-safety recommendation — RocksDB bounds, Auto Loader mode, or the DLT full-refresh checklist, from the matching reference.
Error Handling
| Error | Cause | Solution |
|---|---|---|
ConcurrentDeleteDeleteException | Manual OPTIMIZE races auto-compaction (D01) | Run pre-optimize-check.sh; don't manually OPTIMIZE an auto-compacted table, or disable auto-compact first. |
ConcurrentAppendException on an LC table | MERGE predicate not scoped to clustering keys (D02) | Route the MERGE to merge-rewriter; narrow the ON predicate to the clustering keys. |
DELTA_FILE_NOT_FOUND_DETAILED | VACUUM deleted checkpoint-pinned files (D03) | recover-streaming-source.py --failure file-not-found; restore via time travel if in retention, else reprocess/reset. |
DIFFERENT_DELTA_TABLE_READ_BY_STREAMING_SOURCE | CREATE OR REPLACE minted a new UUID (D12) | The old checkpoint is dead — new checkpoint + backfill; the hook prevents this going forward. |
| Driver OOM, heap looks fine | Off-heap RocksDB state (D05) | Bound state-store memory + changelog checkpointing; size state with a watermark. |
UnknownFieldException, stream stopped | Auto Loader addNewColumns default (D10) | Restart to evolve (idempotent sink), or choose rescue/schemaHints deliberately. |
| Hook allowed a destructive op with a warning | Could not verify consumers (no CLI/warehouse) | Advisory — the hook fails open; verify system.streaming.query_progress manually before running it. |
Examples
Example 1: "About to CREATE OR REPLACE a table other jobs stream from."
The PreToolUse hook fires, confirms 2 active consumers via
system.streaming.query_progress, and blocks with: "CREATE OR REPLACE mints a
new UUID → both consumers die with DIFFERENT_DELTA_TABLE_READ_BY_STREAMING_SOURCE;
use ALTER / in-place."
Example 2: "My MERGE into a Liquid-Clustering table fails with ConcurrentAppendException."
The merge-rewriter subagent reads the target's clustering keys via DESCRIBE DETAIL and rewrites the ON predicate to include them, so concurrent writers
touch disjoint file sets — the exception stops without serializing the jobs.
Example 3: "My stream died with DELTA_FILE_NOT_FOUND after a VACUUM."
recover-streaming-source.py --failure file-not-found --time-travel yes →
RESTORE_FROM_TIME_TRAVEL (no data loss): restore the source to a pre-VACUUM version,
restart on the existing checkpoint, then align VACUUM retention with the checkpoint lag.
Example 4: "Before I OPTIMIZE this table."
pre-optimize-check.sh --table main.sales.orders reports COLLISION RISK because
delta.autoOptimize.autoCompact is on — so the skill recommends letting
auto-compaction do it, or disabling it for the maintenance window first.
Resources
${CLAUDE_SKILL_DIR}/references/concurrency-conflicts.md— Delta OCC, auto-compaction collisions (D01), Liquid-Clustering writer conflicts (D02).${CLAUDE_SKILL_DIR}/references/checkpoint-recovery.md— the three-tier streaming checkpoint recovery (D03/D04/D12).${CLAUDE_SKILL_DIR}/references/rocksdb-state-store-tuning.md— bounded off-heap state + changelog checkpointing (D05).${CLAUDE_SKILL_DIR}/references/autoloader-schema-evolution.md— the schema-evolution modes + schemaHints (D10).${CLAUDE_SKILL_DIR}/references/dlt-rebuild-safety.md— DLT thread race, full-refresh data loss, tier cost (D08/D09/D11).${CLAUDE_SKILL_DIR}/scripts/pre-optimize-check.sh— auto-compaction collision probe.${CLAUDE_SKILL_DIR}/scripts/recover-streaming-source.py— 4-way recovery decision tree.${CLAUDE_SKILL_DIR}/hooks/streaming-guard-hook.py— the PreToolUse block for destructive ops on streamed-from tables.${CLAUDE_SKILL_DIR}/agents/merge-rewriter.md— rewrites a MERGE predicate for Liquid Clustering.- Delta concurrency control · Structured Streaming production · Auto Loader schema evolution
What ships with it: 13 files
136.8 KB alongside SKILL.md, 3 of them executable
agents/
- merge-rewriter.md3.4 KB
docs/
- ADR.md12.3 KB
- ONE-PAGER.md5.3 KB
- PRD.md12.9 KB
hooks/
- streaming-guard-hook.pyruns7.9 KB
references/
- autoloader-schema-evolution.md13.4 KB
- checkpoint-recovery.md16.1 KB
- concurrency-conflicts.md15.0 KB
- dlt-rebuild-safety.md13.3 KB
- rocksdb-state-store-tuning.md14.7 KB
scripts/
- pre-optimize-check.shruns3.3 KB
- recover-streaming-source.pyruns10.9 KB
- eval-spec.yaml8.1 KB