Skip to content

Update AGENTS instructions#38678

Draft
EricZhuXYZ wants to merge 1 commit intoapache:masterfrom
EricZhuXYZ:codex/superset
Draft

Update AGENTS instructions#38678
EricZhuXYZ wants to merge 1 commit intoapache:masterfrom
EricZhuXYZ:codex/superset

Conversation

@EricZhuXYZ
Copy link
Copy Markdown

@EricZhuXYZ EricZhuXYZ commented Mar 16, 2026

User description

SUMMARY

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

TESTING INSTRUCTIONS

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

CodeAnt-AI Description

Update LLM/Agent docs, restrict CSV export permission, and speed local image builds for China

What Changed

  • Replaced AGENTS.md with CLAUDE.md and added a new MCP service section describing how to run and develop the fork-specific AI assistant tools and their rules (tool registration, auth, DAOs, testing locations)
  • Block CSV downloads for users without export permission and return a clearer error message when denied; XLSX chart-data export code was removed (XLSX export no longer produced by this endpoint)
  • Use China Tsinghua mirrors for apt/pip in Dockerfiles so image builds fetch packages from faster mirrors when available

Impact

✅ Clearer CSV download permission errors
✅ Faster Docker builds in China
✅ MCP developer guide available for AI assistant tooling

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review Bot commented Mar 16, 2026

Code Review Agent Run #ebe69c

Actionable Suggestions - 0
Additional Suggestions - 3
  • superset-frontend/plugins/legacy-preset-chart-deckgl/src/Multi/Multi.tsx - 1
    • Selector memoization lost · Line 98-100
      Replacing createSelector with a plain function may cause re-renders when dataMask is undefined, as ?? {} creates a new object each time. If simplification was intended, consider a constant empty object to maintain performance.
  • superset-frontend/src/pages/DatasetList/DatasetList.testHelpers.tsx - 1
    • Use specific type for middleware options · Line 353-353
      The type annotation for the getDefaultMiddleware parameter uses 'unknown' for the options, but @reduxjs/toolkit provides the more specific GetDefaultMiddlewareOptions type. Using the specific type improves type safety and aligns with the project's guidelines to avoid 'unknown' when better types are available.
  • superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx - 1
    • Incorrect Type Annotation · Line 155-155
      The type annotation for `getDefaultMiddleware` is incorrect. According to Redux Toolkit docs, `getDefaultMiddleware` accepts an optional options object, so the type should be `(getDefaultMiddleware: (options?: unknown) => Middleware[])` to match the API and maintain consistency with other test files in the codebase.
      Code suggestion
       @@ -155,1 +155,1 @@
      -    middleware: (getDefaultMiddleware: () => Middleware[]) =>
      +    middleware: (getDefaultMiddleware: (options?: unknown) => Middleware[]) =>
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset-frontend/src/types/@reduxjs/toolkit/index.d.ts - 1
    • Prohibited `any` types in declarations · Line 97-98
Review Details
  • Files reviewed - 29 · Commit Range: dbc77d6..dbc77d6
    • Dockerfile
    • pyproject.toml
    • superset-core/pyproject.toml
    • superset-extensions-cli/pyproject.toml
    • superset-frontend/packages/superset-core/src/theme/GlobalStyles.tsx
    • superset-frontend/plugins/legacy-preset-chart-deckgl/src/Multi/Multi.tsx
    • superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartWrapper.tsx
    • superset-frontend/src/SqlLab/components/EditorAutoSync/index.tsx
    • superset-frontend/src/SqlLab/components/EditorWrapper/useAnnotations.ts
    • superset-frontend/src/SqlLab/components/EditorWrapper/useKeywords.ts
    • superset-frontend/src/SqlLab/components/QueryHistory/index.tsx
    • superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx
    • superset-frontend/src/SqlLab/components/TableElement/index.tsx
    • superset-frontend/src/SqlLab/components/TableExploreTree/useTreeData.ts
    • superset-frontend/src/SqlLab/components/TablePreview/index.tsx
    • superset-frontend/src/components/TableSelector/index.tsx
    • superset-frontend/src/hooks/apiResources/catalogs.ts
    • superset-frontend/src/hooks/apiResources/databaseFunctions.ts
    • superset-frontend/src/hooks/apiResources/queries.ts
    • superset-frontend/src/hooks/apiResources/queryValidations.ts
    • superset-frontend/src/hooks/apiResources/schemas.ts
    • superset-frontend/src/hooks/apiResources/sqlEditorTabs.ts
    • superset-frontend/src/hooks/apiResources/tables.ts
    • superset-frontend/src/pages/ChartList/ChartList.testHelpers.tsx
    • superset-frontend/src/pages/DashboardList/DashboardList.permissions.test.tsx
    • superset-frontend/src/pages/DashboardList/DashboardList.testHelpers.tsx
    • superset-frontend/src/pages/DatasetList/DatasetList.testHelpers.tsx
    • superset-frontend/src/types/@reduxjs/toolkit/index.d.ts
    • superset-frontend/src/views/store.ts
  • Files skipped - 3
    • .codex-artifacts/lute-superset-architecture.excalidraw.json - Reason: Filter setting
    • AGENTS.md - Reason: Filter setting
    • docker-compose-light.yml - Reason: Filter setting
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@codeant-ai-for-open-source codeant-ai-for-open-source Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files label Mar 16, 2026
@dosubot dosubot Bot added the doc Namespace | Anything related to documentation label Mar 16, 2026
@codeant-ai-for-open-source
Copy link
Copy Markdown
Contributor

Sequence Diagram

This PR removes the XLSX export path from the explore endpoint and keeps export authorization focused on CSV downloads only. The core runtime change is that CSV requests now perform a direct CSV permission check before generating and returning file content.

sequenceDiagram
    participant Client
    participant ExploreAPI
    participant Security
    participant VizEngine

    Client->>ExploreAPI: Request explore data with csv option
    ExploreAPI->>Security: Check csv download permission

    alt Permission granted
        ExploreAPI->>VizEngine: Generate csv from chart data
        VizEngine-->>ExploreAPI: Csv payload
        ExploreAPI-->>Client: Return csv download
    else Permission denied
        ExploreAPI-->>Client: Return forbidden error
    end
Loading

Generated by CodeAnt AI

@github-actions github-actions Bot added risk:db-migration PRs that require a DB migration api Related to the REST API plugins packages and removed doc Namespace | Anything related to documentation labels Mar 16, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 16, 2026

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit dbc77d6
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/69b8007b1eee1500089151f1
😎 Deploy Preview https://deploy-preview-38678--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread Dockerfile
Comment on lines +42 to +44
# Switch to Tsinghua Debian mirror for faster apt downloads in China
RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources 2>/dev/null \
|| sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list 2>/dev/null \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: This unconditionally rewrites Debian sources to a regional mirror, so apt-get update can fail in environments where that mirror is blocked or unavailable. Make the mirror host configurable and keep the default as deb.debian.org so builds remain reliable globally. [possible bug]

Severity Level: Critical 🚨
- ❌ CI docker-build jobs fail during apt update.
- ❌ Local docker compose setup cannot build images.
- ⚠️ Node and Python stages both affected.
Suggested change
# Switch to Tsinghua Debian mirror for faster apt downloads in China
RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources 2>/dev/null \
|| sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list 2>/dev/null \
# Allow overriding Debian mirror for faster regional builds
ARG DEBIAN_MIRROR_HOST="deb.debian.org"
RUN sed -i "s|deb.debian.org|${DEBIAN_MIRROR_HOST}|g" /etc/apt/sources.list.d/debian.sources 2>/dev/null \
|| sed -i "s|deb.debian.org|${DEBIAN_MIRROR_HOST}|g" /etc/apt/sources.list 2>/dev/null \
Steps of Reproduction ✅
1. Trigger a normal image build path used today, e.g. CI `docker buildx build` in
`.github/workflows/superset-frontend.yml:48` (target `superset-node-ci` at line 51) or
local `docker compose up --build` documented in
`docs/admin_docs/installation/docker-compose.mdx:82`.

2. Build executes `Dockerfile:42-45` (and again `Dockerfile:113-116`) which
unconditionally rewrites Debian host to `mirrors.tuna.tsinghua.edu.cn`.

3. Subsequent package installs call `/app/docker/apt-install.sh` (`Dockerfile:48`,
`Dockerfile:204`, `Dockerfile:258`), and that script runs `apt-get update -qq` at
`docker/apt-install.sh:39`.

4. In networks where Tsinghua mirror is blocked/unavailable, `apt-get update` fails and
the Docker build stops, breaking both CI image builds and local compose bootstrap.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** Dockerfile
**Line:** 42:44
**Comment:**
	*Possible Bug: This unconditionally rewrites Debian sources to a regional mirror, so `apt-get update` can fail in environments where that mirror is blocked or unavailable. Make the mirror host configurable and keep the default as `deb.debian.org` so builds remain reliable globally.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment thread Dockerfile
Comment on lines +126 to +129
RUN pip install --no-cache-dir --upgrade uv -i https://pypi.tuna.tsinghua.edu.cn/simple

# Configure uv to use Tsinghua mirror for all subsequent installs
ENV UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Python package installation is pinned to a single regional index for both pip and uv, so dependency installation fails when that index is inaccessible. Use a configurable index URL with a global default to avoid build outages outside that region. [possible bug]

Severity Level: Critical 🚨
- ❌ Python dependency installation fails across build stages.
- ❌ GitHub docker workflow cannot publish built images.
- ⚠️ Developer docker compose bootstrap blocked by index reachability.
Suggested change
RUN pip install --no-cache-dir --upgrade uv -i https://pypi.tuna.tsinghua.edu.cn/simple
# Configure uv to use Tsinghua mirror for all subsequent installs
ENV UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
ARG PYPI_INDEX_URL="https://pypi.org/simple"
RUN pip install --no-cache-dir --upgrade uv -i ${PYPI_INDEX_URL}
# Configure uv to use the configured package index
ENV UV_INDEX_URL=${PYPI_INDEX_URL}
Steps of Reproduction ✅
1. Start a standard Docker build flow used by project automation:
`.github/workflows/docker.yml:67-89` builds images, and developers run `docker compose up
--build` per `docs/admin_docs/installation/docker-compose.mdx:82`.

2. During `python-base` stage, `Dockerfile:126` installs `uv` via a hardcoded Tsinghua
PyPI URL, then `Dockerfile:129` sets global `UV_INDEX_URL` to the same mirror.

3. Later dependency steps rely on `uv` index configuration (`Dockerfile:187`, `247`,
`275`, `277`, `287`, `296` all run `uv pip install ...`).

4. If `https://pypi.tuna.tsinghua.edu.cn/simple` is inaccessible, `pip install uv` or any
later `uv pip install` fails, aborting image creation.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** Dockerfile
**Line:** 126:129
**Comment:**
	*Possible Bug: Python package installation is pinned to a single regional index for both `pip` and `uv`, so dependency installation fails when that index is inaccessible. Use a configurable index URL with a global default to avoid build outages outside that region.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment on lines +48 to +50
const mockStore = createStore(
(state = { common: { locale } }) => state,
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Creating the Redux store during every render causes a brand-new store instance each time ChartWrapper re-renders, which forces connected children to resubscribe/reset and can lead to avoidable render churn. Initialize the store once with a lazy state initializer so the store identity stays stable across renders. [logic error]

Severity Level: Major ⚠️
- ⚠️ Cartodiagram charts recreate Redux store every rerender.
- ⚠️ Embedded chart subtree resubscribes through Provider repeatedly.
- ⚠️ Map interactions may feel slower with many overlays.
Suggested change
const mockStore = createStore(
(state = { common: { locale } }) => state,
);
const [mockStore] = useState(() =>
createStore((state = { common: { locale } }) => state),
);
Steps of Reproduction ✅
1. Open a Cartodiagram chart in Superset Explore/Dashboard; this viz is registered in
`superset-frontend/src/visualizations/presets/MainPreset.ts:199-211` and loaded via
`loadChart` in
`superset-frontend/plugins/plugin-chart-cartodiagram/src/plugin/index.ts:71-77`.

2. Rendering reaches `CartodiagramPlugin` (`.../src/CartodiagramPlugin.tsx:55-57`) which
mounts `OlChartMap`; `OlChartMap` then creates `ChartLayer`
(`.../src/components/OlChartMap.tsx:37-50` in second effect chunk).

3. `ChartLayer` renders embedded charts with `ReactDOM.render` in
`.../src/components/ChartLayer.tsx:186-194` (and update path `222-230`), which calls
`createChartComponent` in `.../src/util/chartUtil.tsx:41-48`, returning `ChartWrapper`.

4. `ChartWrapper` first renders, then re-renders after `setChart`
(`.../src/components/ChartWrapper.tsx:39, 42-44`); on each render it executes
`createStore` at `:48-50`, creating a new Redux store identity and forcing provider
subtree resubscription churn.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/plugins/plugin-chart-cartodiagram/src/components/ChartWrapper.tsx
**Line:** 48:50
**Comment:**
	*Logic Error: Creating the Redux store during every render causes a brand-new store instance each time `ChartWrapper` re-renders, which forces connected children to resubscribe/reset and can lead to avoidable render churn. Initialize the store once with a lazy state initializer so the store identity stays stable across renders.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment on lines +95 to +109
({
isSuccess,
isError,
data,
}: {
isSuccess: boolean;
isError: boolean;
data?: CatalogOption[];
}) => {
if (isSuccess) {
onSuccess?.(data || EMPTY_CATALOGS, forceRefresh);
}
if (isError) {
onError?.(result.error as ClientErrorObject);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The lazy query error handler reads result.error from the hook state instead of the error returned by the trigger promise. During a failed refetch, result.error can still be stale or undefined, so the callback may receive the wrong error payload and show an incorrect message. Use the error field from the resolved trigger result. [logic error]

Severity Level: Major ⚠️
- ⚠️ Catalog refresh may show wrong error details.
- ⚠️ SQL Lab selector error messaging becomes unreliable.
- ⚠️ Datasource/Table selector diagnostics become less actionable.
Suggested change
({
isSuccess,
isError,
data,
}: {
isSuccess: boolean;
isError: boolean;
data?: CatalogOption[];
}) => {
if (isSuccess) {
onSuccess?.(data || EMPTY_CATALOGS, forceRefresh);
}
if (isError) {
onError?.(result.error as ClientErrorObject);
}
({
isSuccess,
isError,
data,
error,
}: {
isSuccess: boolean;
isError: boolean;
data?: CatalogOption[];
error?: ClientErrorObject;
}) => {
if (isSuccess) {
onSuccess?.(data || EMPTY_CATALOGS, forceRefresh);
}
if (isError) {
onError?.(error as ClientErrorObject);
}
}
Steps of Reproduction ✅
1. Open a screen using `DatabaseSelector` (used in
`src/SqlLab/components/SqlEditorLeftBar/index.tsx:137`, `:190`,
`src/components/TableSelector/index.tsx:353`, and
`src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx:1865`).

2. In `src/components/DatabaseSelector/index.tsx:487`, click refresh
(`onClick={refetchCatalogs}`), which calls `useCatalogs().refetch` from
`src/hooks/apiResources/catalogs.ts:116-118`.

3. `refetch` executes `fetchData(dbId, true)` and then `trigger({ dbId, forceRefresh
}).then(...)` at `catalogs.ts:94`; when the request fails, callback enters `isError`
branch at `catalogs.ts:107`.

4. The error callback currently passes `result.error` (`catalogs.ts:108`) instead of the
lazy trigger result error. This can be stale/undefined for that request, so
`DatabaseSelector` onError (`index.tsx:80-87`) may show generic/wrong error handling.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/hooks/apiResources/catalogs.ts
**Line:** 95:109
**Comment:**
	*Logic Error: The lazy query error handler reads `result.error` from the hook state instead of the error returned by the `trigger` promise. During a failed refetch, `result.error` can still be stale or undefined, so the callback may receive the wrong error payload and show an incorrect message. Use the `error` field from the resolved trigger result.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment on lines +184 to 186
merge: (currentCache: QueryResult, newItems: QueryResult) => {
currentCache.result.push(...newItems.result);
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The pagination merge only appends result and never refreshes count, but the UI uses count to decide whether to keep loading more pages. If total rows change between requests (common in query history), this stale value can cause premature stop or repeated extra fetches. Update count from each new page before appending results. [logic error]

Severity Level: Major ⚠️
- ⚠️ SQL Lab history can stop before all rows.
- ⚠️ Infinite scroll can trigger unnecessary extra requests.
- ❌ Query history list may be incomplete for users.
Suggested change
merge: (currentCache: QueryResult, newItems: QueryResult) => {
currentCache.result.push(...newItems.result);
},
merge: (currentCache: QueryResult, newItems: QueryResult) => {
currentCache.count = newItems.count;
currentCache.result.push(...newItems.result);
},
Steps of Reproduction ✅
1. Open SQL Lab Query History with backend persistence enabled; `QueryHistory` calls
`useEditorQueriesQuery({ editorId, pageIndex })` at
`superset-frontend/src/SqlLab/components/QueryHistory/index.tsx:80-85`.

2. Scroll to bottom so pagination runs; the effect at `index.tsx:113-117` loads next pages
while `loadedDataCount < totalCount`, where `totalCount` is `data?.count` from
`index.tsx:111`.

3. The RTK query cache merge at
`superset-frontend/src/hooks/apiResources/queries.ts:184-186` appends `result` but never
updates `count`, so cache keeps first page's total.

4. If later page responses return a different total (realistic in query history as rows
are added/removed while viewing), pagination decisions use stale `totalCount`, causing
either premature stop (missing rows) or extra repeated fetches.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/hooks/apiResources/queries.ts
**Line:** 184:186
**Comment:**
	*Logic Error: The pagination merge only appends `result` and never refreshes `count`, but the UI uses `count` to decide whether to keep loading more pages. If total rows change between requests (common in query history), this stale value can cause premature stop or repeated extra fetches. Update `count` from each new page before appending results.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

Comment on lines +123 to 130
serializeQueryArgs: ({
queryArgs: { dbId, schema },
}: {
queryArgs: Pick<FetchTablesQueryParams, 'dbId' | 'schema'>;
}) => ({
dbId,
schema,
}),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The cache key for table queries ignores the selected catalog, so switching catalogs while keeping the same database and schema can reuse stale cached table results from the previous catalog instead of fetching fresh data. Include catalog in serializeQueryArgs so cache entries are isolated per catalog. [logic error]

Severity Level: Major ⚠️
- ❌ Add Dataset table list can show wrong catalog tables.
- ❌ Datasource Editor may bind users to incorrect table.
- ⚠️ Users must manual refresh to recover correct list.
Suggested change
serializeQueryArgs: ({
queryArgs: { dbId, schema },
}: {
queryArgs: Pick<FetchTablesQueryParams, 'dbId' | 'schema'>;
}) => ({
dbId,
schema,
}),
serializeQueryArgs: ({
queryArgs: { dbId, catalog, schema },
}: {
queryArgs: Pick<FetchTablesQueryParams, 'dbId' | 'catalog' | 'schema'>;
}) => ({
dbId,
catalog,
schema,
}),
Steps of Reproduction ✅
1. Open a real TableSelector entry flow such as Add Dataset left panel
(`superset-frontend/src/features/datasets/AddDataset/LeftPanel/index.tsx:206`) or
Datasource Editor
(`superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx:2062`),
both of which render `<TableSelector>`.

2. In `TableSelector`, table loading uses `useTables({ dbId, catalog: currentCatalog,
schema: currentSchema })`
(`superset-frontend/src/components/TableSelector/index.tsx:189-192`), which calls
`useTablesQuery` in `tables.ts`
(`superset-frontend/src/hooks/apiResources/tables.ts:197-199`).

3. The request includes catalog in URL params (`catalog_name`) (`tables.ts:116`), but
cache key serialization only uses `{ dbId, schema }` (`tables.ts:123-130`), so different
catalogs with same db+schema share one cache entry.

4. Reproduce by selecting catalog A + schema S, then switching catalog and re-selecting
schema S (catalog reset behavior is in `TableSelector` `internalCatalogChange`,
`index.tsx:274-281`): `useTablesQuery` can serve cached results from catalog A instead of
fetching catalog B tables, showing stale table options.
Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/hooks/apiResources/tables.ts
**Line:** 123:130
**Comment:**
	*Logic Error: The cache key for table queries ignores the selected catalog, so switching catalogs while keeping the same database and schema can reuse stale cached table results from the previous catalog instead of fetching fresh data. Include `catalog` in `serializeQueryArgs` so cache entries are isolated per catalog.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
👍 | 👎

{
skip: !(hasValidator && dbId && sql),
selectFromResult: ({ isLoading, isError, error, data }) => {
selectFromResult: ({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The selector builds a new array with data.map(...) on every selector run, which breaks RTK Query's shallow memoization for selectFromResult and can cause unnecessary re-renders on unrelated Redux updates. Cache the mapped annotations by data reference inside a selector factory so the returned data reference stays stable when the source data has not changed. [performance]

Severity Level: Major ⚠️
- ⚠️ SQL Lab editor does extra annotation recomputation work.
- ⚠️ Frequent selection updates can trigger unnecessary editor updates.

true,
)
.then(({ data }) => {
.then(({ data }: { data?: TableOptionsData }) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The lazy RTK query trigger resolves with { isSuccess, isError, data, error } even on failures, so relying on .catch(...) means API errors are silently ignored and errorPayload is never set. Handle isError inside .then(...) to surface failures correctly. [logic error]

Severity Level: Major ⚠️
- ⚠️ SQL Lab schema-load failures show no error banner.
- ⚠️ Users retry blindly when tables API fails.

if (dbId && (!result.currentData || forceRefresh)) {
trigger({ dbId, catalog, forceRefresh }).then(
({ isSuccess, isError, data }) => {
({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The lazy query error handler is wired to result.error (state from useSchemasQuery) instead of the error returned by the current trigger(...) call. When a refetch fails, this can pass a stale/undefined error object to onError, causing incorrect error reporting. Capture error from the trigger result and pass that to onError. [logic error]

Severity Level: Major ⚠️
- ⚠️ Schema refresh may lose backend error details.
- ⚠️ DatabaseSelector may show generic error fallback message.

@sadpandajoe
Copy link
Copy Markdown
Member

@EricZhuXYZ please update the PR description. The title says that you are trying to update the agents instructions, yet there are a lot of files being touched that doe not have to do with the agent instructions.

@sadpandajoe sadpandajoe marked this pull request as draft March 17, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the REST API packages plugins review:draft risk:db-migration PRs that require a DB migration size/XXL size:XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants