codeant-ai-for-open-source[bot] commented on code in PR #37625:
URL: https://github.com/apache/superset/pull/37625#discussion_r2757462267


##########
superset-frontend/eslint-rules/eslint-plugin-i18n-strings/index.ts:
##########
@@ -22,21 +22,26 @@
  * @author Apache
  */
 
+import type { Rule } from 'eslint';
+import type { Node } from 'estree';
+
 
//------------------------------------------------------------------------------
 // Rule Definition
 
//------------------------------------------------------------------------------
 
-/** @type {import('eslint').Rule.RuleModule} */
-module.exports = {
+const plugin: { rules: Record<string, Rule.RuleModule> } = {
   rules: {
     'no-template-vars': {
-      create(context) {
-        function handler(node) {
-          if (node.arguments.length) {
-            const firstArgs = node.arguments[0];
+      create(context: Rule.RuleContext): Rule.RuleListener {
+        function handler(node: Node): void {
+          const callNode = node as Node & {
+            arguments: Array<Node & { expressions?: Node[] }>;
+          };
+          if (callNode.arguments.length) {
+            const firstArgs = callNode.arguments[0];
             if (

Review Comment:
   **Suggestion:** The `no-template-vars` rule only inspects the first argument 
of the translation call, so template literals with variables in later arguments 
(e.g. the plural string in `tn`) are never reported, which breaks the rule's 
intent of banning variables in any translation template string. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Translation rule misses variable-containing plural templates.
   - ⚠️ Linter allows translation strings with runtime variables.
   - ⚠️ Developers may ship non-extractable translations.
   ```
   </details>
   
   ```suggestion
               arguments: Array<Node & { type: string; expressions?: Node[] }>;
             };
   
             for (const arg of callNode.arguments ?? []) {
               if (
                 arg.type === 'TemplateLiteral' &&
                 (arg as Node & { expressions?: Node[] }).expressions?.length
               ) {
                 context.report({
                   node,
                   message:
                     "Don't use variables in translation string templates. 
Flask-babel is a static translation service, so it can't handle strings that 
include variables",
                 });
                 break;
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run ESLint with this plugin enabled on the repo (plugin file at
   superset-frontend/eslint-rules/eslint-plugin-i18n-strings/index.ts). The 
rule's handler is
   defined at lines ~36-45 in that file.
   
   2. Lint a source file that calls tn('singular template', 'plural template', 
n) where the
   plural template (2nd argument) is a TemplateLiteral containing expressions 
(e.g. tn(`You
   have ${count} item`, `You have ${count} items`, count)). The current handler 
only inspects
   the first argument (lines ~40-44) and ignores the second argument.
   
   3. Observe that ESLint does not report a violation for the plural 
TemplateLiteral with
   embedded expressions, allowing variable-containing translation templates to 
pass linting.
   
   4. Confirm by searching the codebase for tn( occurrences (e.g. rg "tn\\(") — 
plural
   translation calls are common in UI labels/buttons — demonstrating this path 
is reachable
   by normal lint runs. The proposed change iterates over all arguments and 
will catch
   template literals in any argument.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/eslint-rules/eslint-plugin-i18n-strings/index.ts
   **Line:** 38:42
   **Comment:**
        *Logic Error: The `no-template-vars` rule only inspects the first 
argument of the translation call, so template literals with variables in later 
arguments (e.g. the plural string in `tn`) are never reported, which breaks the 
rule's intent of banning variables in any translation template string.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-calendar/src/Calendar.ts:
##########
@@ -96,12 +98,13 @@ function Calendar(element, props) {
     }
     const timestamps = metricsData[metric];
     const extents = d3Extent(Object.keys(timestamps), key => timestamps[key]);
-    const step = (extents[1] - extents[0]) / (steps - 1);
+    const step =

Review Comment:
   **Suggestion:** The code assumes that `d3Extent` always returns numeric 
bounds, but when a metric has no data (or only non-numeric values) 
`extents[0]`/`extents[1]` will be `undefined`, so using them in arithmetic and 
as the domain for `createLinearScale` will yield `NaN` and can cause the 
legend/color scale setup and downstream rendering to fail for that metric. 
[logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Calendar chart breaks for metrics with no data.
   - ⚠️ Dashboard tiles may show empty/errored calendar visuals.
   - ⚠️ Data edge-cases produce inconsistent colors.
   ```
   </details>
   
   ```suggestion
       if (extents[0] == null || extents[1] == null) {
         return;
       }
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Inspect the per-metric loop in
   superset-frontend/plugins/legacy-plugin-chart-calendar/src/Calendar.ts 
beginning near line
   99 inside function Calendar. The code computes `extents` from timestamps via 
d3Extent on
   line 100.
   
   2. Trigger the Calendar rendering with a metric whose timestamps object is 
empty (e.g.,
   metricsData[metric] === {}), or where timestamp values are non-numeric so 
d3Extent returns
   [undefined, undefined]. This is a realistic dataset scenario when a metric 
has no samples
   or upstream aggregation produced no buckets.
   
   3. On an empty metric, `extents[0]` and/or `extents[1]` will be 
null/undefined. The code
   then executes the arithmetic on line 101 which uses those undefined values 
and produces
   NaN, which propagates into color scale creation and legend calculation.
   
   4. Reproduce by mounting Calendar with props.data.data containing a metric 
key that maps
   to an empty object, then observe that legend/color calculations fail or 
produce invalid
   values and the calendar either renders incorrectly or throws at runtime.
   
   Note: The suggested early-return (or alternatively skipping this metric) 
prevents
   downstream arithmetic on undefined extents.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-calendar/src/Calendar.ts
   **Line:** 101:101
   **Comment:**
        *Logic Error: The code assumes that `d3Extent` always returns numeric 
bounds, but when a metric has no data (or only non-numeric values) 
`extents[0]`/`extents[1]` will be `undefined`, so using them in arithmetic and 
as the domain for `createLinearScale` will yield `NaN` and can cause the 
legend/color scale setup and downstream rendering to fail for that metric.
   
   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.
   ```
   </details>



##########
superset-frontend/packages/superset-ui-core/src/chart/components/FallbackComponent.tsx:
##########
@@ -39,7 +38,13 @@ export default function FallbackComponent({ error, height, 
width }: Props) {
         <div>
           <b>{t('Oops! An error occurred!')}</b>
         </div>
-        <code>{error ? getErrorMessage(error) : 'Unknown Error'}</code>
+        <code>
+          {error instanceof Error
+            ? error.message
+            : error
+              ? String(error)

Review Comment:
   **Suggestion:** Rendering the raw error message directly in the UI can 
unintentionally expose internal implementation details or sensitive backend 
error information to end users; instead, this fallback component should display 
only a generic, non-sensitive error message. [security]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Chart fallback UI may expose internal error messages.
   - ⚠️ Unit tests depend on FallbackComponent rendering.
   - ⚠️ Dashboard charts use SuperChart fallback component.
   ```
   </details>
   
   ```suggestion
             {'Unknown Error'}
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render a chart that triggers the fallback path. SuperChart imports the 
default fallback
   at `src/chart/components/SuperChart.tsx:39` (import 
DefaultFallbackComponent) and passes
   props here: `src/chart/components/SuperChart.tsx:221-222` where it renders
   `<FallbackComponent width={width} height={height} {...props} />`.
   
   2. Cause a chart render error (for example, a chart plugin throws during 
render). The
   error propagates to SuperChart's error handling and it renders the default
   FallbackComponent at `src/chart/components/SuperChart.tsx:221-222`.
   
   3. When FallbackComponent renders, it executes the code at
   `src/chart/components/FallbackComponent.tsx:41-46` (the existing code block) 
and will
   display the raw `error.message` or `String(error)` directly in the UI.
   
   4. Observe the UI showing the raw error text inside a <code> block (file and 
lines:
   
`superset-frontend/packages/superset-ui-core/src/chart/components/FallbackComponent.tsx:41-46`).
   This can reveal internal stack/messages returned by chart plugins or backend 
errors. Note:
   tests reference this component at
   `test/chart/components/FallbackComponent.test.tsx:23-28`, so changing 
display behavior
   will affect those tests.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/packages/superset-ui-core/src/chart/components/FallbackComponent.tsx
   **Line:** 42:45
   **Comment:**
        *Security: Rendering the raw error message directly in the UI can 
unintentionally expose internal implementation details or sensitive backend 
error information to end users; instead, this fallback component should display 
only a generic, non-sensitive error message.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.tsx:
##########
@@ -29,24 +28,46 @@ const NOOP = () => {};
 export const DEFAULT_MAX_ZOOM = 16;
 export const DEFAULT_POINT_RADIUS = 60;
 
-const propTypes = {
-  width: PropTypes.number,
-  height: PropTypes.number,
-  aggregatorName: PropTypes.string,
-  clusterer: PropTypes.object,
-  globalOpacity: PropTypes.number,
-  hasCustomMetric: PropTypes.bool,
-  mapStyle: PropTypes.string,
-  mapboxApiKey: PropTypes.string.isRequired,
-  onViewportChange: PropTypes.func,
-  pointRadius: PropTypes.number,
-  pointRadiusUnit: PropTypes.string,
-  renderWhileDragging: PropTypes.bool,
-  rgb: PropTypes.array,
-  bounds: PropTypes.array,
-};
+interface Viewport {
+  longitude: number;
+  latitude: number;
+  zoom: number;
+  isDragging?: boolean;
+}
+
+interface Clusterer {
+  getClusters(bbox: number[], zoom: number): GeoJSONLocation[];
+}
+
+interface GeoJSONLocation {
+  geometry: {
+    coordinates: [number, number];
+  };
+  properties: Record<string, number | string | boolean | null | undefined>;
+}
 
-const defaultProps = {
+interface MapBoxProps {
+  width?: number;
+  height?: number;
+  aggregatorName?: string;
+  clusterer?: Clusterer;
+  globalOpacity?: number;
+  hasCustomMetric?: boolean;
+  mapStyle?: string;
+  mapboxApiKey: string;
+  onViewportChange?: (viewport: Viewport) => void;
+  pointRadius?: number;
+  pointRadiusUnit?: string;
+  renderWhileDragging?: boolean;
+  rgb?: (string | number)[];
+  bounds?: [[number, number], [number, number]];

Review Comment:
   **Suggestion:** The `bounds` prop is declared optional but is immediately 
used with non-null assertions in `fitBounds` and bbox computation, so a caller 
omitting `bounds` (which the type currently allows) will trigger a runtime 
error instead of being caught by TypeScript. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Component initialization fails without bounds.
   - ⚠️ Map viewport computation (fitBounds) affected.
   - ⚠️ No fallback bounds defined in defaultProps.
   ```
   </details>
   
   ```suggestion
     bounds: [[number, number], [number, number]];
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open MapBox.tsx and inspect MapBoxProps: bounds is declared optional at 
line 63
   (bounds?: [[number, number], [number, number]];).
   
   2. Locate constructor usage at MapBox.tsx lines ~82-94 where 
fitBounds(bounds!) is called:
   new WebMercatorViewport(...).fitBounds(bounds!). The code uses bounds with a 
non-null
   assertion during construction.
   
   3. Also locate render-time usage at MapBox.tsx lines ~135-142 where bbox is 
computed from
   bounds using bounds! to build array entries; both sites assume bounds exists.
   
   4. Reproduce by rendering <MapBox ... /> without a bounds prop. Since 
defaultProps does
   not supply bounds, the constructor will call fitBounds(undefined) (due to 
bounds!), which
   will throw (or produce invalid mercator values) causing 
initialization/runtime failure.
   The exact failing lines are visible in the file at the constructor and bbox 
computation
   sites.
   
   5. This is a realistic failure for any consumer that omits bounds (type 
allows omission).
   Making bounds required or adding runtime guards will prevent the crash.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.tsx
   **Line:** 63:63
   **Comment:**
        *Type Error: The `bounds` prop is declared optional but is immediately 
used with non-null assertions in `fitBounds` and bbox computation, so a caller 
omitting `bounds` (which the type currently allows) will trigger a runtime 
error instead of being caught by TypeScript.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.ts:
##########
@@ -213,8 +228,8 @@ function CountryMap(element, props) {
   if (map) {
     drawMap(map);
   } else {
-    const url = countries[country];
-    d3.json(url, (error, mapData) => {
+    const url = (countries as Record<string, string>)[country];
+    d3.json(url, (error: unknown, mapData: GeoData) => {
       if (error) {

Review Comment:
   **Suggestion:** The code assumes that `country` always maps to a valid URL 
in `countries`, but `transformProps` can pass `null` or an unmapped value, so 
`url` may be `undefined` and `d3.json` will be called with an invalid URL, 
leading to a failed request or runtime error instead of a controlled 
user-facing error message. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Missing map data for unmapped country causes request failure.
   - ⚠️ User may not see controlled error message.
   - ⚠️ Console shows d3/json request errors.
   ```
   </details>
   
   ```suggestion
       if (!url) {
         const countryName =
           countryOptions.find(x => x[0] === country)?.[1] || country;
         d3.select(element).html(
           `<div class="alert alert-danger">Could not load map data for 
${countryName}</div>`,
         );
         return;
       }
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render a CountryMap chart (file:
   
superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.ts). 
The
   map-loading logic is at the hunk starting line 228 (`const map = 
maps[country];`) in the
   PR diff.
   
   2. Provide props where the `country` prop is null, undefined, or a value not 
present in
   the countries lookup (this can happen if transformProps or upstream control 
passes an
   unmapped ISO key). The code then computes `const url = (countries as 
Record<string,
   string>)[country];` at lines shown in the hunk.
   
   3. If `url` is undefined, the current code calls `d3.json(url, ...)` with an 
invalid URL.
   This results in a failed network request or runtime error inside d3.json 
before the
   existing in-callback error branch can run, leading to either console errors 
or no
   user-facing message.
   
   4. Observable result: no graceful "Could not load map data" alert is shown 
in some failure
   modes; instead the request may fail silently or throw earlier. Reproduce by 
invoking the
   legacy country map with an unmapped `country` value (e.g., via chart control 
or by editing
   the props passed to the renderer) and observe network and console behavior.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.ts
   **Line:** 233:233
   **Comment:**
        *Possible Bug: The code assumes that `country` always maps to a valid 
URL in `countries`, but `transformProps` can pass `null` or an unmapped value, 
so `url` may be `undefined` and `d3.json` will be called with an invalid URL, 
leading to a failed request or runtime error instead of a controlled 
user-facing error message.
   
   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.
   ```
   </details>



##########
superset-frontend/eslint-rules/eslint-plugin-theme-colors/index.ts:
##########
@@ -0,0 +1,130 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * @fileoverview Rule to warn about literal colors
+ * @author Apache
+ */
+
+import type { Rule } from 'eslint';
+import type { Node, SourceLocation } from 'estree';
+
+const COLOR_KEYWORDS: string[] = require('./colors');
+
+function hasHexColor(quasi: string): boolean {
+  const regex = /#([a-f0-9]{3}|[a-f0-9]{4}(?:[a-f0-9]{2}){0,2})\b/gi;
+  return !!quasi.match(regex);
+}
+
+function hasRgbColor(quasi: string): boolean {
+  const regex = /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)/i;
+  return !!quasi.match(regex);
+}
+
+function hasLiteralColor(quasi: string, strict: boolean = false): boolean {
+  // matches literal colors at the start or end of a CSS prop
+  return COLOR_KEYWORDS.some((color: string) => {
+    const regexColon = new RegExp(`: ${color}`);
+    const regexSemicolon = new RegExp(` ${color};`);
+    return (
+      !!quasi.match(regexColon) ||
+      !!quasi.match(regexSemicolon) ||
+      (strict && quasi === color)
+    );
+  });
+}
+
+const WARNING_MESSAGE: string =
+  'Theme color variables are preferred over rgb(a)/hex/literal colors';
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+interface TemplateElementNode extends Node {
+  value?: { raw: string };
+  parent?: Node & {
+    parent?: Node & { loc?: SourceLocation | null };
+  };
+}
+
+interface LiteralNode extends Node {
+  value?: string;
+  parent?: Node;
+}
+
+const plugin: { rules: Record<string, Rule.RuleModule> } = {
+  rules: {
+    'no-literal-colors': {
+      create(context: Rule.RuleContext): Rule.RuleListener {
+        const warned: string[] = [];
+        return {
+          TemplateElement(node: Node): void {
+            const templateNode = node as TemplateElementNode;
+            const rawValue = templateNode?.value?.raw;
+            const isChildParentTagged =
+              templateNode?.parent?.parent?.type === 
'TaggedTemplateExpression';
+            const isChildParentArrow =
+              templateNode?.parent?.parent?.type === 'ArrowFunctionExpression';
+            const isParentTemplateLiteral =
+              templateNode?.parent?.type === 'TemplateLiteral';
+            const loc = templateNode?.parent?.parent?.loc;
+            const locId = loc && JSON.stringify(loc);
+            const hasWarned = locId ? warned.includes(locId) : false;
+            if (
+              !hasWarned &&
+              (isChildParentTagged ||
+                (isChildParentArrow && isParentTemplateLiteral)) &&
+              rawValue &&
+              (hasLiteralColor(rawValue) ||
+                hasHexColor(rawValue) ||
+                hasRgbColor(rawValue))
+            ) {
+              context.report(node, loc as SourceLocation, WARNING_MESSAGE);
+              if (locId) {
+                warned.push(locId);
+              }
+            }
+          },
+          Literal(node: Node): void {
+            const literalNode = node as LiteralNode;
+            const value = literalNode?.value;
+            const isParentProperty = literalNode?.parent?.type === 'Property';
+            const locId = JSON.stringify(node.loc);
+            const hasWarned = warned.includes(locId);
+
+            if (

Review Comment:
   **Suggestion:** The `Literal` visitor assumes the literal `value` is always 
a string and passes it directly into helper functions that call `.match`, but 
in ESTree/ESLint ASTs `Literal.value` can be numbers, booleans, null, RegExp, 
etc., so encountering a non-zero number or a RegExp literal in an object 
property will cause a runtime `TypeError` when `.match` is called on a 
non-string value; adding a type check to ensure only string literals are 
processed avoids the crash while preserving the intended behavior. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ ESLint process can crash during lint runs.
   - ⚠️ CI lint job may fail unexpectedly.
   - ⚠️ Affects files with numeric/RegExp property literals.
   ```
   </details>
   
   ```suggestion
               if (typeof value !== 'string') {
                 return;
               }
   
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run ESLint that loads this plugin (file:
   superset-frontend/eslint-rules/eslint-plugin-theme-colors/index.ts).
   
   2. During linting, the rule's visitor method Literal at index.ts:105 is 
invoked for AST
   Literal nodes.
   
   3. If a property's value is a non-string literal (e.g. property: 42 or 
property: /abc/),
   the code at index.ts:107 assigns value to a non-string (number or RegExp).
   
   4. The helper functions hasLiteralColor / hasHexColor / hasRgbColor (called 
at
   index.ts:116-118) call .match on the passed value; calling .match on a 
non-string throws
   TypeError at runtime.
   
   5. Observe ESLint process crashing during lint run with a TypeError stack 
trace
   originating from index.ts lines 116-118 when processing such a file.
   
   6. Reproduce locally by adding a test file with an object property using a 
numeric literal
   (e.g. { color: 42 }) and running eslint against that file; the visitor at 
index.ts:105-123
   will execute and trigger the crash.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/eslint-rules/eslint-plugin-theme-colors/index.ts
   **Line:** 112:112
   **Comment:**
        *Type Error: The `Literal` visitor assumes the literal `value` is 
always a string and passes it directly into helper functions that call 
`.match`, but in ESTree/ESLint ASTs `Literal.value` can be numbers, booleans, 
null, RegExp, etc., so encountering a non-zero number or a RegExp literal in an 
object property will cause a runtime `TypeError` when `.match` is called on a 
non-string value; adding a type check to ensure only string literals are 
processed avoids the crash while preserving the intended behavior.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.tsx:
##########
@@ -186,7 +231,7 @@ class ScatterPlotGlowOverlay extends PureComponent {
           if (location.properties.cluster) {
             let clusterLabel = clusterLabelMap[i];
             const scaledRadius = roundDecimal(
-              (clusterLabel / maxLabel) ** 0.5 * radius,
+              ((clusterLabel as number) / maxLabel) ** 0.5 * radius,

Review Comment:
   **Suggestion:** The cluster radius scaling divides by `maxLabel` without 
guarding against it being zero or non‑finite; if all cluster aggregation values 
are zero (e.g., `sum` of metrics that are all 0), `maxLabel` becomes 0 and the 
expression `(clusterLabel / maxLabel) ** 0.5` yields `NaN`, causing the arc 
radius to be `NaN` and cluster circles to fail to render. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Cluster markers disappear for zero-valued aggregations.
   - ⚠️ Map visualization inaccurate for zero-sum datasets.
   - ⚠️ Affects cluster rendering in ScatterPlotGlowOverlay.
   ```
   </details>
   
   ```suggestion
               const safeMaxLabel =
                 Number.isFinite(maxLabel) && maxLabel > 0 ? maxLabel : 1;
               const scaledRadius = roundDecimal(
                 ((clusterLabel as number) / safeMaxLabel) ** 0.5 * radius,
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Build and run the frontend with this PR applied so the modified component 
is used.
   
   2. Trigger rendering of the map visualization that uses 
ScatterPlotGlowOverlay (the
   component in
   
superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.tsx).
 The
   redraw logic executes in the redraw method (final file) which iterates 
clusterLabelMap and
   reaches the cluster rendering branch around lines 232-236.
   
   3. Provide cluster data where every cluster aggregation value is 0 (for 
example, the
   server returns cluster properties with point_count > 0 but sum = 0 for a 
'sum'
   aggregation). The code computes maxLabel from clusterLabelMap (earlier in 
redraw) and if
   all values are zero maxLabel == 0.
   
   4. When execution reaches the code at lines 232-236, the expression 
((clusterLabel as
   number) / maxLabel) ** 0.5 performs division by zero, producing NaN. The 
computed
   scaledRadius becomes NaN and is passed to ctx.arc(...), causing the cluster 
circle drawing
   to fail or be invisible. This reproduces a missing cluster markers situation 
in the map UI
   (observed at the paths and line numbers above).
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.tsx
   **Line:** 233:234
   **Comment:**
        *Logic Error: The cluster radius scaling divides by `maxLabel` without 
guarding against it being zero or non‑finite; if all cluster aggregation values 
are zero (e.g., `sum` of metrics that are all 0), `maxLabel` becomes 0 and the 
expression `(clusterLabel / maxLabel) ** 0.5` yields `NaN`, causing the arc 
radius to be `NaN` and cluster circles to fail to render.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.tsx:
##########
@@ -234,23 +279,28 @@ class ScatterPlotGlowOverlay extends PureComponent {
             }
           } else {
             const defaultRadius = radius / 6;
-            const radiusProperty = location.properties.radius;
-            const pointMetric = location.properties.metric;
-            let pointRadius =
-              radiusProperty === null ? defaultRadius : radiusProperty;
-            let pointLabel;
+            const radiusProperty = location.properties.radius as number | null;
+            const pointMetric = location.properties.metric as
+              | number
+              | string
+              | null;
+            let pointRadius: number =
+              radiusProperty === null
+                ? defaultRadius
+                : (radiusProperty as number);
+            let pointLabel: string | number | undefined;
 
             if (radiusProperty !== null) {

Review Comment:
   **Suggestion:** The radius handling treats only `null` as "missing" but not 
`undefined`, so when `properties.radius` is absent (undefined) the code 
initializes `pointRadius` to `undefined` and still enters the conversion block 
for Kilometers/Miles/Pixels, leading to operations like `kmToPixels(undefined, 
...)` and further math on `undefined`, which will produce `NaN` radii and 
inconsistent or invisible points instead of cleanly falling back to the default 
radius. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Some point markers render incorrectly or not at all.
   - ⚠️ Point-size scaling for datasets missing radius values.
   - ⚠️ Affects non-cluster point rendering logic in the component.
   ```
   </details>
   
   ```suggestion
                   radiusProperty == null
                     ? defaultRadius
                     : (radiusProperty as number);
                 let pointLabel: string | number | undefined;
   
                 if (radiusProperty != null) {
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start the app with the PR's ScatterPlotGlowOverlay component included.
   
   2. Use a dataset where some point features omit the radius property entirely
   (properties.radius is undefined rather than explicitly null). The component 
reads
   radiusProperty at line 282 in the file and currently narrows it as "as 
number | null".
   
   3. Execution reaches the non-cluster branch (around lines 279-293). Because 
the code only
   treats null as "missing", an undefined radiusProperty causes pointRadius to 
be set to
   (radiusProperty as number) — effectively undefined — rather than 
defaultRadius.
   
   4. The code then enters the conversion block (lines starting 293) and can 
call
   kmToPixels(undefined, ...), perform Number(undefined) or other math, 
producing NaN for
   pointRadius and resulting in invisible or incorrectly sized points on the 
map. Observing
   map points missing for rows where properties.radius was omitted reproduces 
the issue;
   relevant code locations are in the file at the lines above.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-map-box/src/ScatterPlotGlowOverlay.tsx
   **Line:** 289:293
   **Comment:**
        *Logic Error: The radius handling treats only `null` as "missing" but 
not `undefined`, so when `properties.radius` is absent (undefined) the code 
initializes `pointRadius` to `undefined` and still enters the conversion block 
for Kilometers/Miles/Pixels, leading to operations like `kmToPixels(undefined, 
...)` and further math on `undefined`, which will produce `NaN` radii and 
inconsistent or invisible points instead of cleanly falling back to the default 
radius.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.tsx:
##########
@@ -29,24 +28,46 @@ const NOOP = () => {};
 export const DEFAULT_MAX_ZOOM = 16;
 export const DEFAULT_POINT_RADIUS = 60;
 
-const propTypes = {
-  width: PropTypes.number,
-  height: PropTypes.number,
-  aggregatorName: PropTypes.string,
-  clusterer: PropTypes.object,
-  globalOpacity: PropTypes.number,
-  hasCustomMetric: PropTypes.bool,
-  mapStyle: PropTypes.string,
-  mapboxApiKey: PropTypes.string.isRequired,
-  onViewportChange: PropTypes.func,
-  pointRadius: PropTypes.number,
-  pointRadiusUnit: PropTypes.string,
-  renderWhileDragging: PropTypes.bool,
-  rgb: PropTypes.array,
-  bounds: PropTypes.array,
-};
+interface Viewport {
+  longitude: number;
+  latitude: number;
+  zoom: number;
+  isDragging?: boolean;
+}
+
+interface Clusterer {
+  getClusters(bbox: number[], zoom: number): GeoJSONLocation[];
+}
+
+interface GeoJSONLocation {
+  geometry: {
+    coordinates: [number, number];
+  };
+  properties: Record<string, number | string | boolean | null | undefined>;
+}
 
-const defaultProps = {
+interface MapBoxProps {
+  width?: number;
+  height?: number;
+  aggregatorName?: string;
+  clusterer?: Clusterer;

Review Comment:
   **Suggestion:** The `clusterer` prop is typed as optional even though the 
component unconditionally dereferences it with a non-null assertion and calls 
`getClusters`, which means any consumer that omits `clusterer` (and TypeScript 
currently permits that) will cause a runtime crash instead of a compile-time 
error. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Runtime crash during MapBox render (clusters computation).
   - ⚠️ Any parent component that omits clusterer triggers failure.
   - ⚠️ No default clusterer provided in defaultProps.
   ```
   </details>
   
   ```suggestion
     clusterer: Clusterer;
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Inspect MapBoxProps in
   superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.tsx and 
find clusterer
   declared optional at line 53 (clusterer?: Clusterer;). This defines allowed 
consumer
   usage.
   
   2. Find the render-time dereference at MapBox.tsx lines ~137-144 (clusters 
computation):
   clusterer!.getClusters(bbox, Math.round(viewport.zoom)); The code uses a 
non-null
   assertion and assumes clusterer is present.
   
   3. Reproduce by mounting <MapBox ... /> without providing a clusterer prop. 
Because
   defaultProps does not provide a clusterer, the runtime value will be 
undefined.
   
   4. When render runs (initial mount or re-render), execution reaches
   clusterer!.getClusters(...), invoking undefined.getClusters and producing a 
TypeError. The
   call site is visible in the file at the clusters assignment (MapBox.tsx 
around lines
   137-144).
   
   5. This is a realistic crash path because many consumers might forget to 
pass clusterer
   (the type currently permits omission), and there is no runtime guard before 
calling
   getClusters.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-map-box/src/MapBox.tsx
   **Line:** 53:53
   **Comment:**
        *Type Error: The `clusterer` prop is typed as optional even though the 
component unconditionally dereferences it with a non-null assertion and calls 
`getClusters`, which means any consumer that omits `clusterer` (and TypeScript 
currently permits that) will cause a runtime crash instead of a compile-time 
error.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-horizon/src/transformProps.ts:
##########
@@ -16,7 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-export default function transformProps(chartProps) {
+import { ChartProps } from '@superset-ui/core';
+
+export default function transformProps(chartProps: ChartProps) {
   const { height, width, formData, queriesData } = chartProps;
   const { horizonColorScale, seriesHeight } = formData;

Review Comment:
   **Suggestion:** The code destructures `horizonColorScale` and `seriesHeight` 
from `formData` using camelCase keys that don't match the control names 
(`horizon_color_scale` and `series_height`), so both values will be 
`undefined`, causing `colorScale` to ignore user configuration and 
`parseInt(seriesHeight, 10)` to yield `NaN`, breaking the chart's layout. 
[logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Horizon chart color scale ignored by user configuration.
   - ❌ Chart layout broken due to NaN series height.
   - ⚠️ Affects all dashboards using Horizon chart plugin.
   - ⚠️ Visualization regressions visible to end users.
   ```
   </details>
   
   ```suggestion
     const {
       horizon_color_scale: horizonColorScale,
       series_height: seriesHeight,
     } = formData;
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Build and run the frontend with the PR changes applied so the chart 
plugin code at
   superset-frontend/plugins/legacy-plugin-chart-horizon/src/transformProps.ts 
is used.
   
   2. Open a dashboard containing the Horizon chart and edit its controls: set 
a custom color
   scale and change the series height in the chart controls UI (these controls 
are the
   sources of formData and are wired in snake_case like `horizon_color_scale` /
   `series_height` in the control definitions).
   
   3. When the chart renders, the transformProps function at
   
superset-frontend/plugins/legacy-plugin-chart-horizon/src/transformProps.ts:23 
executes
   the line `const { horizonColorScale, seriesHeight } = formData;` (line 
referenced above),
   which looks for camelCase keys that do not exist in the incoming formData 
object.
   
   4. As a result, horizonColorScale and seriesHeight are undefined. The 
returned object sets
   colorScale to undefined and calls `parseInt(seriesHeight, 10)` producing NaN 
for
   seriesHeight. Observe the chart either ignoring the configured color scale 
or rendering
   incorrectly (height/spacing broken) in the UI where Horizon charts are used.
   
   5. Repeatable: every time the Horizon chart is used with non-default control 
values, the
   mis-mapping will occur because control values are provided under snake_case 
keys by the
   form system.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-horizon/src/transformProps.ts
   **Line:** 23:23
   **Comment:**
        *Logic Error: The code destructures `horizonColorScale` and 
`seriesHeight` from `formData` using camelCase keys that don't match the 
control names (`horizon_color_scale` and `series_height`), so both values will 
be `undefined`, causing `colorScale` to ignore user configuration and 
`parseInt(seriesHeight, 10)` to yield `NaN`, breaking the chart's layout.
   
   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.
   ```
   </details>



##########
superset-frontend/eslint-rules/eslint-plugin-i18n-strings/index.ts:
##########
@@ -76,29 +84,39 @@ module.exports = {
 
           // Check for Button components
           if (parent.type === 'JSXExpressionContainer') {
-            const jsx = parent.parent;
+            const jsx = (parent as Node & { parent?: Node }).parent as
+              | (Node & {
+                  openingElement?: { name: { name: string } };
+                })
+              | undefined;
             if (jsx?.type === 'JSXElement') {
-              const elementName = jsx.openingElement.name.name;
+              const elementName = jsx.openingElement?.name.name;
               return elementName === 'Button';
             }
           }
 
           return false;
         }
 
-        function handler(node) {
-          if (node.arguments.length) {
-            const firstArg = node.arguments[0];
+        function handler(node: Node): void {
+          const callNode = node as Node & {
+            arguments: Array<Node & { value?: string }>;
+          };
+          if (callNode.arguments.length) {
+            const firstArg = callNode.arguments[0];
             if (
               firstArg.type === 'Literal' &&
               typeof firstArg.value === 'string'
             ) {

Review Comment:
   **Suggestion:** The `sentence-case-buttons` rule only examines the first 
argument of a `t`/`tn` call, so button labels passed as additional string 
literal arguments (for example the plural label in `tn`) can still be in Title 
Case without being flagged, which undermines the rule's goal of enforcing 
sentence case for all button text. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Button labels in plural args remain Title Case.
   - ⚠️ UI text inconsistency across buttons.
   - ⚠️ Linter enforcement weakened for button text.
   ```
   </details>
   
   ```suggestion
               arguments: Array<Node & { type: string; value?: string }>;
             };
   
             for (const arg of callNode.arguments ?? []) {
               if (
                 arg.type === 'Literal' &&
                 typeof arg.value === 'string'
               ) {
                 const text = arg.value;
   
                 if (
                   isButtonContext(node as Node & { parent?: Node }) &&
                   isTitleCase(text)
                 ) {
                   const sentenceCase = text
                     .toLowerCase()
                     .replace(/^\w/, (c: string) => c.toUpperCase());
                   context.report({
                     node: arg,
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run ESLint using the plugin (file:
   superset-frontend/eslint-rules/eslint-plugin-i18n-strings/index.ts). The
   sentence-case-buttons handler is defined around lines ~101-116.
   
   2. Lint a file where a Button label is provided via tn('singular', 'Plural 
Title Case', n)
   or where a component's button prop receives multiple string args and the 
second/other
   literal is Title Case (e.g. tn('Delete', 'Delete Datasets', count)).
   
   3. Because the current handler only checks the first argument (firstArg at 
line ~103), the
   Title Case label in the second argument is not reported. The lint run shows 
no violation
   whereas the proposed rule should flag the Title Case plural/button label.
   
   4. Verify prevalence by searching the codebase for tn( and multi-argument 
t()/tn() usages
   (e.g. rg "tn\\(") — these plural forms are used in UI where button labels 
and plural
   strings appear, making this a realistic lint gap.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/eslint-rules/eslint-plugin-i18n-strings/index.ts
   **Line:** 103:110
   **Comment:**
        *Logic Error: The `sentence-case-buttons` rule only examines the first 
argument of a `t`/`tn` call, so button labels passed as additional string 
literal arguments (for example the plural label in `tn`) can still be in Title 
Case without being flagged, which undermines the rule's goal of enforcing 
sentence case for all button text.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.ts:
##########
@@ -60,17 +73,17 @@ function CountryMap(element, props) {
   const container = element;
   const format = getNumberFormatter(numberFormat);
   const linearColorScale = getSequentialSchemeRegistry()
-    .get(linearColorScheme)
-    .createLinearScale(d3Extent(data, v => v.metric));
+    .get(linearColorScheme)!
+    .createLinearScale(d3Extent(data, v => v.metric) as [number, number]);

Review Comment:
   **Suggestion:** The sequential color scheme lookup uses a non-null assertion 
and immediately calls `createLinearScale`, so if `linearColorScheme` is missing 
or refers to a scheme that has been removed, 
`getSequentialSchemeRegistry().get(linearColorScheme)` will return `undefined` 
and the code will throw at runtime when trying to call `createLinearScale` on 
it; this should fall back gracefully instead of crashing the chart. [possible 
bug]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Country map chart crashes on invalid color scheme.
   - ⚠️ Chart initialization halts before map drawing.
   - ⚠️ Browser console shows uncaught TypeError.
   ```
   </details>
   
   ```suggestion
     const sequentialScheme = 
getSequentialSchemeRegistry().get(linearColorScheme);
     const linearColorScale =
       sequentialScheme?.createLinearScale(
         d3Extent(data, v => v.metric) as [number, number],
       ) ?? (() => '');
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render a CountryMap chart in the frontend with the PR code deployed 
(component
   implementation at
   
superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.ts). 
The code
   that creates the sequential color scale is at the hunk starting line 73 
(`const
   linearColorScale = ...`) in the PR diff.
   
   2. Trigger chart rendering with props where linearColorScheme is either 
undefined, null,
   or an invalid key (this happens when the chart control sends a scheme name 
that no longer
   exists). The call flow is: chart renderer -> legacy plugin loader -> this 
CountryMap
   function defined in the file above, which immediately executes the lines at 
73–78.
   
   3. At runtime getSequentialSchemeRegistry().get(linearColorScheme) returns 
undefined for a
   missing/invalid key; the code uses a non-null assertion (`!`) and then calls
   `.createLinearScale(...)` on undefined. This causes a TypeError thrown 
synchronously
   during chart initialization, preventing the rest of CountryMap from running.
   
   4. Observable result: the chart fails to render and an uncaught error is 
visible in
   browser console; no graceful user-facing error message is shown because the 
exception
   occurs before map drawing or error-handling branches. Confirm reproduction 
by supplying an
   invalid linearColorScheme value in the chart controls or inspecting 
network/props for
   charts using this legacy plugin.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-country-map/src/CountryMap.ts
   **Line:** 75:77
   **Comment:**
        *Possible Bug: The sequential color scheme lookup uses a non-null 
assertion and immediately calls `createLinearScale`, so if `linearColorScheme` 
is missing or refers to a scheme that has been removed, 
`getSequentialSchemeRegistry().get(linearColorScheme)` will return `undefined` 
and the code will throw at runtime when trying to call `createLinearScale` on 
it; this should fall back gracefully instead of crashing the chart.
   
   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.
   ```
   </details>



##########
superset-frontend/plugins/legacy-plugin-chart-horizon/src/HorizonChart.tsx:
##########
@@ -96,13 +97,13 @@ class HorizonChart extends PureComponent {
       offsetX,
     } = this.props;
 
-    let yDomain;
+    let yDomain: [number, number] | undefined;
     if (colorScale === 'overall') {
-      const allValues = data.reduce(
+      const allValues = data.reduce<DataValue[]>(
         (acc, current) => acc.concat(current.values),
         [],
       );
-      yDomain = d3Extent(allValues, d => d.y);
+      yDomain = d3Extent(allValues, d => d.y) as [number, number];

Review Comment:
   **Suggestion:** When `colorScale` is set to "overall" and the aggregated 
`data` contains no numeric values, `d3Extent` can return `[undefined, 
undefined]`, which is then cast to `[number, number]` and passed down as 
`yDomain`, causing `HorizonRow` to build a y-scale with an invalid domain and 
potentially producing NaN-based rendering behavior. Guard the extent result by 
checking that there are values and that both min and max are non-null before 
assigning `yDomain`, otherwise leave it undefined so each row can fall back to 
its own extent logic. [possible bug]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Charts with colorScale='overall' may render incorrectly.
   - ⚠️ Empty series produce invalid y-domain values.
   - ⚠️ HorizonRow scale computation receives invalid input.
   ```
   </details>
   
   ```suggestion
         if (allValues.length > 0) {
           const [min, max] = d3Extent(allValues, d => d.y);
           if (min != null && max != null) {
             yDomain = [min, max];
           }
         }
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open the file at
   superset-frontend/plugins/legacy-plugin-chart-horizon/src/HorizonChart.tsx 
and locate the
   renderer at the render() method (lines ~86-120 in the PR hunk). The code 
that computes
   yDomain starts at line 100 in the PR diff: "let yDomain..." (see
   existing_code_start_line).
   
   2. Provide chart data where colorScale prop is set to 'overall' (the 
component reads this
   from this.props at lines ~86-96). In practice, any caller that renders 
<HorizonChart
   colorScale="overall" data={...} /> will follow this branch.
   
   3. Supply data such that data.reduce produces an allValues array that is 
empty or where
   all DataValue.y entries are undefined/null (for example, data = [{ key: 
['a'], values: []
   }, { key: ['b'], values: [] }]). With the current code, d3Extent(allValues, 
d => d.y) will
   return [undefined, undefined].
   
   4. The existing code casts the result to [number, number] (line 106), 
assigning yDomain =
   [undefined, undefined]. HorizonRow receives yDomain (mapped in the render 
loop) and will
   attempt to build a d3 scale with invalid domain leading to NaN coordinates 
or no
   rendering.
   
   5. Observed behavior: rows render incorrectly (gaps, no bars, console 
warnings from d3
   scale usage) when all series are empty or contain non-numeric y values. The 
proposed
   improved_code guards the extent result by checking length and min/max 
non-null before
   setting yDomain, preventing passing an invalid domain to HorizonRow.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/plugins/legacy-plugin-chart-horizon/src/HorizonChart.tsx
   **Line:** 106:106
   **Comment:**
        *Possible Bug: When `colorScale` is set to "overall" and the aggregated 
`data` contains no numeric values, `d3Extent` can return `[undefined, 
undefined]`, which is then cast to `[number, number]` and passed down as 
`yDomain`, causing `HorizonRow` to build a y-scale with an invalid domain and 
potentially producing NaN-based rendering behavior. Guard the extent result by 
checking that there are values and that both min and max are non-null before 
assigning `yDomain`, otherwise leave it undefined so each row can fall back to 
its own extent logic.
   
   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.
   ```
   </details>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to