Skip to content

fix(feature-flags): don't connect to db before model is loaded (fixes #2066 unit regression + latent boot bug) - #2073

Merged
jung-thomas merged 1 commit into
DEVfrom
fix/env-flags-attachments-regression
Aug 28, 2026
Merged

jung-thomas merged 1 commit into
DEVfrom
fix/env-flags-attachments-regression

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

Problem

After #2066 (flags → DB config), the unit suite went red (~205 fails across unrelated services, all HTTP 500 "Query was not inferred and includes '*'").

Root cause (a latent RUNTIME bug, not just tests)

srv/server.js calls isFlagEnabled('MCP_AUTH_ENABLED') inside cds.on('bootstrap') — before cds.model is linked. The generic db-flags.js resolver's cold-cache path kicks off a background refreshFeatureFlags() → cds.connect.to('db'), which eagerly caches the db service against the partial, service-less bootstrap model (proven: primary db built once with a 211-def model vs the full 737-def model, and it persists). SQLService.cqn4sql then short-circuits for any target missing from that stale db model, so SELECT * … expand reaches CQN2SQLite.SELECT_expand with a literal '*' → 500. The poisoned db is process-wide, hence the broad blast radius. This would poison HANA at runtime too — it's not SQLite-specific — so it's a latent production boot bug, caught before deploy.

Fix

scheduleRefresh() no-ops while cds.model is unset (if (!cds.model) return;). The bootstrap flag read then returns the flag's declared registry default — the documented cold-cache behavior — and the real warm-up still runs in the served handler once the model is fully loaded. Runtime-safe on every dialect; nothing legitimately reads a flag before the model exists except that one bootstrap line.

Also fixes 2 stale tests (kg-path-v2-or-v1, kg-path-between-handler) that still toggled the now-DB-driven KG_PATH_V2_ENABLED via vi.stubEnv → switched to __setFlagForTest.

Verification

  • Full vitest run --project unit: 8804 passed, 0 test failures (the file-level failures in that run are pre-existing env/parallelism: cds.test hook timeouts under 1194-file load, srv-qa parsers.bundle.mjs needs the pretest hook, hugo-apps needs npm run setup).
  • Spot-check: search-service + navigator-groups + kg-path-between-handler = 65/65 green (all were failing pre-fix).

Fixes the DEV-red from #2066. Should merge before any deploy of the flag-migration work.

…2066 unit regression)

#2066 migrated on/off feature flags from env vars to ImsConfig-backed DB
rows. The generic resolver srv/lib/feature-flags/db-flags.js exposes a
synchronous isFlagEnabled() that, on a cold cache, fires a background
refreshFeatureFlags() via scheduleRefresh().

server.js reads isFlagEnabled('MCP_AUTH_ENABLED') inside cds.on('bootstrap')
to install the MCP kill switch. At bootstrap time cds.model is not yet
linked, so the fire-and-forget scheduleRefresh() called cds.connect.to('db')
prematurely. cds.connect caches cds.db eagerly (cds.services.db = the pending
promise) and resolves the db service's model from the partial, service-less
model that exists mid-bootstrap. That poisoned primary-db instance then
persists for the process, so cqn4sql can no longer resolve service-qualified
targets (SearchService.SearchableItems etc.), leaving '*' unexpanded and
every later service read throwing 500 "Query was not inferred and includes
'*' in the columns" — ~205 unit failures. content-delta-flags.js was
unaffected only because none of its getters run during bootstrap.

Fix: scheduleRefresh() no-ops while cds.model is unset. The bootstrap read
then returns the flag's declared registry default (the intended cold-cache
behavior, per the server.js comment) and the real warm-up runs in the
'served' handler once the model is fully loaded. Runtime-safe on every
dialect: the poison is model resolution, not SQLite-specific rendering.

Also update two stale kg-path tests (kg-path-v2-or-v1, kg-path-between-handler)
that still toggled the now-DB-driven KG_PATH_V2_ENABLED via vi.stubEnv; switch
them to __setFlagForTest/__resetFlagsForTest, matching the pattern #2066
already applied to the other migrated-flag tests.
@jung-thomas
jung-thomas merged commit 201ba78 into DEV Aug 28, 2026
4 checks passed
@jung-thomas
jung-thomas deleted the fix/env-flags-attachments-regression branch August 28, 2026 16:00
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