Repository: prometheus/prometheus (language: go)

Issue:
time() function with error
### What did you do?

Run `time()` function in prometheus web console.

### What did you expect to see?

work well

### What did you see instead? Under which circumstances?

Got errors:

```
Error executing query: Cannot convert undefined or null to object
```





### System information

_No response_

### Prometheus version

```text
Version	2.49.0-rc.0
Revision	c4c8d59c14ea558a4878fb014cc954347c317978
Branch	HEAD
BuildUser	root@e59256874f10
BuildDate	20231212-11:17:29
GoVersion	go1.21.5
```


### Prometheus configuration file

_No response_

### Alertmanager version

_No response_

### Alertmanager configuration file

_No response_

### Logs

_No response_


Discussion / hints:
This is caused by a missing type check [here](https://github.com/prometheus/prometheus/blob/main/web/ui/react-app/src/pages/graph/Panel.tsx#L196), since it doesn't expect a scalar input. If you wrap the query result in a vector, i.e. `vector(time())`, it does produce an output.

Fix patch:
diff --git a/web/ui/react-app/src/pages/graph/DataTable.tsx b/web/ui/react-app/src/pages/graph/DataTable.tsx
index 901d7bb48d7..1885c7a80f6 100644
--- a/web/ui/react-app/src/pages/graph/DataTable.tsx
+++ b/web/ui/react-app/src/pages/graph/DataTable.tsx
@@ -24,7 +24,7 @@ export interface DataTableProps {
       }
     | {
         resultType: 'string';
-        result: string;
+        result: SampleValue;
       };
   useLocalTime: boolean;
 }
diff --git a/web/ui/react-app/src/pages/graph/GraphHeatmapHelpers.ts b/web/ui/react-app/src/pages/graph/GraphHeatmapHelpers.ts
index d564959cb80..d8b249c308f 100644
--- a/web/ui/react-app/src/pages/graph/GraphHeatmapHelpers.ts
+++ b/web/ui/react-app/src/pages/graph/GraphHeatmapHelpers.ts
@@ -1,10 +1,12 @@
+import { DataTableProps } from './DataTable';
 import { GraphProps, GraphSeries } from './Graph';
 
-export function isHeatmapData(data: GraphProps['data']) {
-  if (!data?.result?.length || data?.result?.length < 2) {
+export function isHeatmapData(data: DataTableProps['data']) {
+  if (data?.resultType === 'scalar' || data?.resultType === 'string' || !data?.result?.length || data?.result?.length < 2) {
     return false;
   }
-  const result = data.result;
+  // Type assertion to prevent TS2349 error.
+  const result = data.result as GraphProps['data']['result'];
   const firstLabels = Object.keys(result[0].metric).filter((label) => label !== 'le');
   return result.every(({ metric }) => {
     const labels = Object.keys(metric).filter((label) => label !== 'le');


Test patch:
diff --git a/web/ui/react-app/src/pages/graph/DataTable.test.tsx b/web/ui/react-app/src/pages/graph/DataTable.test.tsx
index d6974cf9062..1252b5bfcf7 100755
--- a/web/ui/react-app/src/pages/graph/DataTable.test.tsx
+++ b/web/ui/react-app/src/pages/graph/DataTable.test.tsx
@@ -338,7 +338,7 @@ describe('DataTable', () => {
     const dataTableProps: DataTableProps = {
       data: {
         resultType: 'string',
-        result: 'string',
+        result: [1572098246.599, 'test'],
       },
       useLocalTime: false,
     };
@@ -346,7 +346,7 @@ describe('DataTable', () => {
     it('renders a string row', () => {
       const table = dataTable.find(Table);
       const rows = table.find('tr');
-      expect(rows.text()).toEqual('stringt');
+      expect(rows.text()).toEqual('stringtest');
     });
   });
 });
diff --git a/web/ui/react-app/src/pages/graph/GraphHeatmapHelpers.test.ts b/web/ui/react-app/src/pages/graph/GraphHeatmapHelpers.test.ts
new file mode 100644
index 00000000000..26c44be68b2
--- /dev/null
+++ b/web/ui/react-app/src/pages/graph/GraphHeatmapHelpers.test.ts
@@ -0,0 +1,66 @@
+import { DataTableProps } from './DataTable';
+import { isHeatmapData } from './GraphHeatmapHelpers';
+
+describe('GraphHeatmapHelpers', () => {
+  it('isHeatmapData should return false for scalar and string resultType', () => {
+    let data = {
+      resultType: 'scalar',
+      result: [1703091180.125, '1703091180.125'],
+    } as DataTableProps['data'];
+    expect(isHeatmapData(data)).toBe(false);
+
+    data = {
+      resultType: 'string',
+      result: [1704305680.332, '2504'],
+    } as DataTableProps['data'];
+    expect(isHeatmapData(data)).toBe(false);
+  });
+
+  it('isHeatmapData should return false for a vector and matrix if length < 2', () => {
+    let data = {
+      resultType: 'vector',
+      result: [
+        {
+          metric: {
+            __name__: 'my_gauge',
+            job: 'target',
+          },
+          value: [1703091180.683, '6'],
+        },
+      ],
+    } as DataTableProps['data'];
+    expect(isHeatmapData(data)).toBe(false);
+
+    data = {
+      resultType: 'matrix',
+      result: [
+        {
+          metric: {},
+          values: [[1703091180.683, '6']],
+        },
+      ],
+    } as DataTableProps['data'];
+    expect(isHeatmapData(data)).toBe(false);
+  });
+
+  it('isHeatmapData should return true for valid heatmap data', () => {
+    const data = {
+      resultType: 'matrix',
+      result: [
+        {
+          metric: {
+            le: '100',
+          },
+          values: [[1703091180.683, '6']],
+        },
+        {
+          metric: {
+            le: '1000',
+          },
+          values: [[1703091190.683, '6.1']],
+        },
+      ],
+    } as DataTableProps['data'];
+    expect(isHeatmapData(data)).toBe(true);
+  });
+});