fix: display tauri error messages instead of object dumps

This commit is contained in:
thibaud-leclere 2026-04-14 11:19:42 +02:00
parent 0c0d8e1caa
commit abaf86a6ec
5 changed files with 55 additions and 12 deletions

View file

@ -2,6 +2,7 @@ import { useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { open } from "@tauri-apps/plugin-dialog";
import { createProject, getProject, updateProject } from "../../lib/api";
import { getErrorMessage } from "../../lib/errors";
export default function ProjectForm() {
const navigate = useNavigate();
@ -49,8 +50,7 @@ export default function ProjectForm() {
window.dispatchEvent(new Event("orchai:refresh-projects"));
navigate("/");
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
setError(message);
setError(getErrorMessage(err));
} finally {
setLoading(false);
}

View file

@ -5,6 +5,7 @@ import {
deleteTuleapCredentials,
testTuleapConnection,
} from "../../lib/api";
import { getErrorMessage } from "../../lib/errors";
import type { TuleapCredentialsSafe } from "../../lib/types";
export default function SettingsPage() {
@ -43,7 +44,7 @@ export default function SettingsPage() {
setPassword("");
setSuccess("Credentials saved.");
} catch (err: unknown) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
} finally {
setSaving(false);
}
@ -56,7 +57,7 @@ export default function SettingsPage() {
const msg = await testTuleapConnection();
setSuccess(msg);
} catch (err: unknown) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
} finally {
setTesting(false);
}
@ -74,7 +75,7 @@ export default function SettingsPage() {
setPassword("");
setSuccess("Credentials deleted.");
} catch (err: unknown) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
} finally {
setDeleting(false);
}

View file

@ -10,6 +10,7 @@ import {
getWorktreeDiff,
retryTicket,
} from "../../lib/api";
import { getErrorMessage } from "../../lib/errors";
import type { ProcessedTicket, Worktree } from "../../lib/types";
function statusBadgeClass(status: string): string {
@ -88,7 +89,7 @@ export default function TicketDetail() {
setDiff(null);
}
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
}
}
@ -103,7 +104,7 @@ export default function TicketDetail() {
await retryTicket(ticketId);
await loadData();
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
}
setLoading(false);
}
@ -115,7 +116,7 @@ export default function TicketDetail() {
await cancelTicket(ticketId);
await loadData();
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
}
setLoading(false);
}
@ -128,7 +129,7 @@ export default function TicketDetail() {
await applyFixToBranch(worktree.id, targetBranch);
await loadData();
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
}
setLoading(false);
}
@ -142,7 +143,7 @@ export default function TicketDetail() {
setWorktree(null);
setDiff(null);
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
}
setLoading(false);
}

View file

@ -1,6 +1,7 @@
import { useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { addTracker, getTrackerFields } from "../../lib/api";
import { getErrorMessage } from "../../lib/errors";
import type { FilterGroup, TrackerField, AgentConfig } from "../../lib/types";
import FilterBuilder from "./FilterBuilder";
@ -29,7 +30,7 @@ export default function TrackerConfig() {
setFields(result);
setFieldsLoaded(true);
} catch (err: unknown) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
} finally {
setFieldsLoading(false);
}
@ -52,7 +53,7 @@ export default function TrackerConfig() {
await addTracker(projectId, Number(trackerId), trackerLabel, pollingInterval, agentConfig, filters);
navigate(`/projects/${projectId}`);
} catch (err: unknown) {
setError(err instanceof Error ? err.message : String(err));
setError(getErrorMessage(err));
} finally {
setLoading(false);
}

40
src/lib/errors.ts Normal file
View file

@ -0,0 +1,40 @@
export function getErrorMessage(err: unknown): string {
if (err instanceof Error) {
return err.message;
}
if (typeof err === "string") {
return err;
}
if (err && typeof err === "object") {
const withMessage = err as { message?: unknown; error?: unknown };
if (typeof withMessage.message === "string") {
return withMessage.message;
}
if (typeof withMessage.error === "string") {
return withMessage.error;
}
if (
withMessage.message &&
typeof withMessage.message === "object" &&
"message" in withMessage.message
) {
const nested = withMessage.message as { message?: unknown };
if (typeof nested.message === "string") {
return nested.message;
}
}
try {
return JSON.stringify(err);
} catch {
// fallthrough to String below
}
}
return String(err);
}