Skip to content

fix(sqlmesh): resolve DuckDB connection-config conflict blocking state init#30

Closed
Doctacon wants to merge 3 commits into
mainfrom
fix/sqlmesh-state-conn-conflict
Closed

fix(sqlmesh): resolve DuckDB connection-config conflict blocking state init#30
Doctacon wants to merge 3 commits into
mainfrom
fix/sqlmesh-state-conn-conflict

Conversation

@Doctacon
Copy link
Copy Markdown
Owner

Summary

  • Register only the backend-matching SQLMesh gateway so Context.engine_adapters stops eagerly opening the other backend's connection at snapshot-evaluation time.
  • Pass config={"custom_user_agent": f"SQLMesh/{__version__}"} when ensure_motherduck_databases() opens the md: URL so DuckDB's process-global handle cache doesn't reject SQLMesh's later open with "different configuration than existing connections".
  • Retain a dedicated state_connection at data/sqlmesh_state.duckdb on both gateways (already present, kept for SQLMesh's MotherDuck-as-state warning + h3-extension conflict).

Also sweeps in 2 pre-existing commits on main (examples/ removal, Dagster loader + -m entry points) that had not yet been pushed. The Dagster-loader commit is what surfaced this state-conn bug; they merge together cleanly.

Test plan

  • task verify (smoke) ends with RUN_SUCCESS under DATABOX_BACKEND=local on a clean data/ dir
  • task verify (smoke) ends with RUN_SUCCESS under DATABOX_BACKEND=motherduck on a clean data/ dir
  • uv run ruff check packages/ transforms/ → clean
  • uv run mypy packages/ → 50 source files, no issues
  • uv run pytest → 118 passed, 1 out-of-scope flake (ebird/test_idempotency.py, tracked separately)
  • tests/test_motherduck_autocreate.py updated for new kwargs-based duckdb.connect call signature

Full run tails + tool output captured in .loom/evidence/20260423-sqlmesh-state-conn-conflict-fix.md. Closes ticket:sqlmesh-state-conn-conflict.

🤖 Generated with Claude Code

Doctacon and others added 3 commits April 22, 2026 17:21
Two changes that landed together because they were found together:

1. analytics.py: drop `from __future__ import annotations` and import
   `AssetExecutionContext` directly instead of via `dg.AssetExecutionContext`.
   Dagster's op-definition validator does an identity check against the
   imported class; PEP 563 turns annotations into strings and the `dg.X`
   attribute form doesn't compare equal. Result: `defs` wouldn't load at
   all since the prior strict-mypy commit introduced the typed `context`
   parameter.

2. Taskfile.yaml: `dagster asset materialize -f <path>` → `-m databox.orchestration.definitions`.
   `dagster dev` drops `-f` entirely — it auto-discovers workspace.yaml
   at the repo root. workspace.yaml itself switches from `python_file`
   to `python_module` so both entry points target the same import path.

Validated with `dagster definitions validate` against both `-m` and
`-w workspace.yaml`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
37 lines of 1Password source code do not justify a top-level directory.
Inlined into docs/secrets.md alongside the existing wiring example — same
"copy-adapt" intent, fewer directories. CLAUDE.md reference dropped.

Reconciled closed loom ticket secrets-pluggable with a follow-up note so
the graph stays truthful — the file was present at close time but has
since been removed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…e init

Two-part fix for the md: URL connection-config conflict that was crashing
`sqlmesh_project` on first run under both backends:

1. `config/settings.py::sqlmesh_config()` now registers only the gateway
   matching `settings.backend`. SQLMesh's `Context.engine_adapters` eagerly
   builds an EngineAdapter for every gateway in `Config.gateways`, so
   registering both made `DATABOX_BACKEND=local` still open a MotherDuck
   connection. A dedicated `state_connection` at `data/sqlmesh_state.duckdb`
   is retained on both paths.

2. `orchestration/_factories.py::ensure_motherduck_databases()` now opens
   `duckdb.connect(database=..., config={"custom_user_agent": f"SQLMesh/{__version__}"})`
   so the md: URL config matches SQLMesh's later open. DuckDB caches a
   process-global handle per `md:?motherduck_token=...` URL and rejects
   subsequent opens with mismatched config dicts.

Verified on a clean `data/` dir: `task verify` ends with RUN_SUCCESS under
both `DATABOX_BACKEND=local` and `DATABOX_BACKEND=motherduck`. Ruff + mypy
clean. See `.loom/evidence/20260423-sqlmesh-state-conn-conflict-fix.md`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Doctacon
Copy link
Copy Markdown
Owner Author

Parking while CI breakage on main is fixed first (per-shard coverage floor). Will rebase + reopen once ci-per-shard-coverage lands.

@Doctacon Doctacon closed this Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant