This is an automated email from the ASF dual-hosted git repository.

nathanma pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/amoro.git


The following commit(s) were added to refs/heads/master by this push:
     new ef4f5cfa4 [UI] Fix stale cache causing 'Table does not exist' error 
(#4075)
ef4f5cfa4 is described below

commit ef4f5cfa422c8cb2c36dbe3e7fdb29af6724e644
Author: Jiwon Park <[email protected]>
AuthorDate: Mon Feb 9 15:35:13 2026 +0900

    [UI] Fix stale cache causing 'Table does not exist' error (#4075)
    
    * [UI] Fix stale cache causing 'Table does not exist' error
    
    Signed-off-by: j1wonpark <[email protected]>
    
    * [UI] Fix race condition in getTableDetails when route changes during 
request
    
    Signed-off-by: Jiwon Park <[email protected]>
    
    ---------
    
    Signed-off-by: j1wonpark <[email protected]>
    Signed-off-by: Jiwon Park <[email protected]>
---
 amoro-web/src/views/tables/components/Details.vue | 31 ++++++++++++++++++-----
 amoro-web/src/views/tables/index.vue              | 21 ++++++++++++++-
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/amoro-web/src/views/tables/components/Details.vue 
b/amoro-web/src/views/tables/components/Details.vue
index 652ed3827..93c26b737 100644
--- a/amoro-web/src/views/tables/components/Details.vue
+++ b/amoro-web/src/views/tables/components/Details.vue
@@ -19,7 +19,7 @@ limitations under the License.
 <script setup lang="ts">
 import { computed, onMounted, reactive, shallowReactive, watch } from 'vue'
 import { useI18n } from 'vue-i18n'
-import { useRoute } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
 import type { ColumnProps } from 'ant-design-vue/es/table'
 import type { DetailColumnItem, IBaseDetailInfo, IColumns, IMap, 
PartitionColumnItem } from '@/types/common.type'
 import { getTableDetail } from '@/services/table.service'
@@ -27,9 +27,13 @@ import { dateFormat } from '@/utils'
 
 const emit = defineEmits<{
   (e: 'setBaseDetailInfo', data: IBaseDetailInfo): void
+  (e: 'tableNotFound', info: { catalog: string; db: string; table: string }): 
void
 }>()
 const { t } = useI18n()
 const route = useRoute()
+const router = useRouter()
+
+const STORAGE_TABLE_KEY = 'easylake-menu-catalog-db-table'
 
 const params = computed(() => {
   return {
@@ -79,14 +83,15 @@ const state = reactive({
 })
 
 async function getTableDetails() {
+  const requestParams = { ...params.value }
+  const { catalog, db, table } = requestParams
+  if (!catalog || !db || !table) {
+    return
+  }
   try {
-    const { catalog, db, table } = params.value
-    if (!catalog || !db || !table) {
-      return
-    }
     state.detailLoading = true
     const result = await getTableDetail({
-      ...params.value,
+      ...requestParams,
     })
     const { pkList = [], tableType, partitionColumnList = [], properties, 
changeMetrics, schema, createTime, tableIdentifier, baseMetrics, tableSummary, 
comment } = result
     state.baseDetailInfo = {
@@ -124,6 +129,20 @@ async function getTableDetails() {
     setBaseDetailInfo()
   }
   catch (error) {
+    const errorMessage = (error as Error)?.message || ''
+    const isNotFoundError = /not exist|not found/i.test(errorMessage)
+
+    if (isNotFoundError) {
+      localStorage.removeItem(STORAGE_TABLE_KEY)
+
+      emit('tableNotFound', {
+        catalog: catalog as string,
+        db: db as string,
+        table: table as string,
+      })
+
+      router.replace({ path: '/tables', query: {} })
+    }
   }
   finally {
     state.detailLoading = false
diff --git a/amoro-web/src/views/tables/index.vue 
b/amoro-web/src/views/tables/index.vue
index 651d27b52..51ad9abe3 100644
--- a/amoro-web/src/views/tables/index.vue
+++ b/amoro-web/src/views/tables/index.vue
@@ -140,6 +140,24 @@ export default defineComponent({
       state.baseInfo = { ...baseInfo }
     }
 
+    const handleTableNotFound = () => {
+      state.baseInfo = {
+        optimizingStatus: '',
+        records: '',
+        tableType: '',
+        tableName: '',
+        createTime: '',
+        tableFormat: '',
+        hasPartition: false,
+        healthScore: -1,
+        smallFileScore: 0,
+        equalityDeleteScore: 0,
+        positionalDeleteScore: 0,
+        comment: '',
+      } as IBaseDetailInfo
+      state.detailLoaded = false
+    }
+
     const onChangeTab = (key: string | number) => {
       const query = { ...route.query }
       query.tab = key.toString()
@@ -210,6 +228,7 @@ export default defineComponent({
       isIceberg,
       hasSelectedTable,
       setBaseDetailInfo,
+      handleTableNotFound,
       goBack,
       onChangeTab,
       sidebarWidth,
@@ -262,7 +281,7 @@ export default defineComponent({
             <div class="tables-main-body">
               <a-tabs v-model:activeKey="activeKey" destroy-inactive-tab-pane 
@change="onChangeTab">
                 <a-tab-pane key="Details" :tab="$t('details')" force-render>
-                  <UDetails ref="detailRef" 
@set-base-detail-info="setBaseDetailInfo" />
+                  <UDetails ref="detailRef" 
@set-base-detail-info="setBaseDetailInfo" 
@table-not-found="handleTableNotFound" />
                 </a-tab-pane>
                 <a-tab-pane v-if="detailLoaded" key="Files" :tab="$t('files')">
                   <UFiles :has-partition="baseInfo.hasPartition" />

Reply via email to