From 2a2048a814062e3eeba18d13754311221fc23ae1 Mon Sep 17 00:00:00 2001 From: Gordon Murray Date: Wed, 10 Jun 2026 19:03:36 +0100 Subject: [PATCH] fix: check response.ok before parsing JSON in frontend fetch calls All five fetch() calls in app.js parsed the response body without checking the HTTP status, so a 4xx/5xx error response was treated as valid data and the UI broke further down. Throw on non-ok responses so failures land in the existing catch handlers and show the normal error messages. Fixes #27 --- CHANGELOG.md | 3 +++ web/vanilla/app.js | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index becbc45..cdabc4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- Frontend fetch calls now check `response.ok` before parsing JSON, so HTTP error responses surface as error states instead of being parsed as data (#27). + ## [0.2.0] - 2026-04-16 ### Added diff --git a/web/vanilla/app.js b/web/vanilla/app.js index 9d04349..d2ef982 100644 --- a/web/vanilla/app.js +++ b/web/vanilla/app.js @@ -69,6 +69,9 @@ class LanceViewer { async checkHealth() { try { const response = await fetch(`${this.apiBase}/healthz`); + if (!response.ok) { + throw new Error(`API error: ${response.status} ${response.statusText}`); + } const data = await response.json(); if (data.ok) { // Show Lance version prominently along with app version @@ -93,6 +96,9 @@ class LanceViewer { async loadDatasets() { try { const response = await fetch(`${this.apiBase}/datasets`); + if (!response.ok) { + throw new Error(`API error: ${response.status} ${response.statusText}`); + } const data = await response.json(); this.elements.datasetList.innerHTML = ''; @@ -134,6 +140,9 @@ class LanceViewer { async loadSchema() { try { const response = await fetch(`${this.apiBase}/datasets/${this.currentDataset}/schema`); + if (!response.ok) { + throw new Error(`API error: ${response.status} ${response.statusText}`); + } const schema = await response.json(); this.elements.schemaDisplay.innerHTML = ''; @@ -167,6 +176,9 @@ class LanceViewer { async loadColumns() { try { const response = await fetch(`${this.apiBase}/datasets/${this.currentDataset}/columns`); + if (!response.ok) { + throw new Error(`API error: ${response.status} ${response.statusText}`); + } const data = await response.json(); this.allColumns = data.columns; @@ -225,6 +237,9 @@ class LanceViewer { } const response = await fetch(`${this.apiBase}/datasets/${this.currentDataset}/rows?${params}`); + if (!response.ok) { + throw new Error(`API error: ${response.status} ${response.statusText}`); + } const data = await response.json(); this.totalRows = data.total;