Skip to content

Commit b2c9252

Browse files
trek-ejakeaturner
authored andcommitted
fix: surface actual error message when service installation fails
Backend returned { error: message } on 400 but frontend expected { message }. catchInternal swallowed Axios errors and returned undefined, causing a generic 'An internal error occurred' message instead of the real reason (already installed, already in progress, not found). - Fix 400 response shape to { success: false, message } in controller - Replace catchInternal with direct error handling in installService, affectService, and forceReinstallService API methods - Extract error.response.data.message from Axios errors so callers see the actual server message
1 parent e7ae6bb commit b2c9252

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

admin/app/controllers/system_controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default class SystemController {
3535
if (result.success) {
3636
response.send({ success: true, message: result.message });
3737
} else {
38-
response.status(400).send({ error: result.message });
38+
response.status(400).send({ success: false, message: result.message });
3939
}
4040
}
4141

admin/inertia/lib/api.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import axios, { AxiosInstance } from 'axios'
1+
import axios, { AxiosError, AxiosInstance } from 'axios'
22
import { ListRemoteZimFilesResponse, ListZimFilesResponse } from '../../types/zim'
33
import { ServiceSlim } from '../../types/services'
44
import { FileEntry } from '../../types/files'
@@ -25,13 +25,19 @@ class API {
2525
}
2626

2727
async affectService(service_name: string, action: 'start' | 'stop' | 'restart') {
28-
return catchInternal(async () => {
28+
try {
2929
const response = await this.client.post<{ success: boolean; message: string }>(
3030
'/system/services/affect',
3131
{ service_name, action }
3232
)
3333
return response.data
34-
})()
34+
} catch (error) {
35+
if (error instanceof AxiosError && error.response?.data?.message) {
36+
return { success: false, message: error.response.data.message }
37+
}
38+
console.error('Error affecting service:', error)
39+
return undefined
40+
}
3541
}
3642

3743
async checkLatestVersion(force: boolean = false) {
@@ -192,13 +198,19 @@ class API {
192198
}
193199

194200
async forceReinstallService(service_name: string) {
195-
return catchInternal(async () => {
201+
try {
196202
const response = await this.client.post<{ success: boolean; message: string }>(
197203
`/system/services/force-reinstall`,
198204
{ service_name }
199205
)
200206
return response.data
201-
})()
207+
} catch (error) {
208+
if (error instanceof AxiosError && error.response?.data?.message) {
209+
return { success: false, message: error.response.data.message }
210+
}
211+
console.error('Error force reinstalling service:', error)
212+
return undefined
213+
}
202214
}
203215

204216
async getChatSuggestions(signal?: AbortSignal) {
@@ -459,13 +471,19 @@ class API {
459471
}
460472

461473
async installService(service_name: string) {
462-
return catchInternal(async () => {
474+
try {
463475
const response = await this.client.post<{ success: boolean; message: string }>(
464476
'/system/services/install',
465477
{ service_name }
466478
)
467479
return response.data
468-
})()
480+
} catch (error) {
481+
if (error instanceof AxiosError && error.response?.data?.message) {
482+
return { success: false, message: error.response.data.message }
483+
}
484+
console.error('Error installing service:', error)
485+
return undefined
486+
}
469487
}
470488

471489
async listCuratedMapCollections() {

0 commit comments

Comments
 (0)