chore: surface swallowed errors + remove dead session_renamed paths
Swallowed-error logging (audit Feature 3):
- file_index.ts:36-37 (git mtime probes): comment — best-effort, project
may not be a git repo.
- useUserEvents.ts:44 / 53 (ws.close on error / unmount): comments —
best-effort, socket may already be closing.
- RightRail.tsx:38 (localStorage write): comment — best-effort, quota or
private mode.
- App.tsx:21 (api.sessions.get for RightRail projectId): replaced silent
catch with console.warn.
- Session.tsx:38, 41 (session fetch + project list for breadcrumb):
replaced silent catches with console.warn.
H1: ProjectSidebar.tsx:189 — dropped the local sessionEvents.emit
({type:'session_renamed'}) after PATCH. Server publishes via
broker.publishUser since v1.4; useUserEvents forwards.
H2: useSessionStream.ts session_renamed case removed (dead — no
server code path publishes session_renamed on the per-session WS
channel; only user channel via broker.publishUser). Also dropped the
session_renamed variant from WsFrame (in apps/web/src/api/types.ts)
to keep the discriminated-union switch exhaustive.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ async function snapMtimes(root: string): Promise<MtimeSnap> {
|
||||
const rootStat = await fs.stat(root);
|
||||
let gitHead: number | null = null;
|
||||
let gitIndex: number | null = null;
|
||||
// best-effort; ignore failure because the project may not be a git repo
|
||||
try { gitHead = (await fs.stat(path.join(root, '.git', 'HEAD'))).mtimeMs; } catch {}
|
||||
try { gitIndex = (await fs.stat(path.join(root, '.git', 'index'))).mtimeMs; } catch {}
|
||||
return { root: rootStat.mtimeMs, gitHead, gitIndex };
|
||||
|
||||
@@ -18,7 +18,10 @@ function SessionRightRail() {
|
||||
function RightRailForSession({ sessionId }: { sessionId: string }) {
|
||||
const [projectId, setProjectId] = useState<string | null>(null);
|
||||
useEffect(() => {
|
||||
api.sessions.get(sessionId).then((s) => setProjectId(s.project_id)).catch(() => {});
|
||||
api.sessions
|
||||
.get(sessionId)
|
||||
.then((s) => setProjectId(s.project_id))
|
||||
.catch((err) => console.warn('RightRail: failed to fetch session', err));
|
||||
}, [sessionId]);
|
||||
if (!projectId) return null;
|
||||
return <RightRail projectId={projectId} />;
|
||||
|
||||
@@ -191,6 +191,5 @@ export type WsFrame =
|
||||
finished_at?: string | null;
|
||||
}
|
||||
| { type: 'messages_deleted'; message_ids: string[]; chat_id?: string }
|
||||
| { type: 'session_renamed'; session_id: string; name: string; chat_id?: string }
|
||||
| { type: 'chat_renamed'; chat_id: string; name: string }
|
||||
| { type: 'error'; message_id?: string; chat_id?: string; error: string };
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
} from '@/components/ui/dialog';
|
||||
import { AddProjectModal } from './AddProjectModal';
|
||||
import { api } from '@/api/client';
|
||||
import { sessionEvents } from '@/hooks/sessionEvents';
|
||||
import { useSidebar } from '@/hooks/useSidebar';
|
||||
import type { SidebarProject } from '@/api/types';
|
||||
import { giteaUrlFor } from '@/lib/projectUrls';
|
||||
@@ -186,7 +185,8 @@ export function ProjectSidebar() {
|
||||
if (!trimmed) return;
|
||||
try {
|
||||
await api.sessions.update(sessionId, { name: trimmed });
|
||||
sessionEvents.emit({ type: 'session_renamed', session_id: sessionId, name: trimmed });
|
||||
// Server publishes session_renamed via broker.publishUser; useUserEvents
|
||||
// forwards onto the bus. No local emit needed.
|
||||
} catch (err) {
|
||||
toast.error(err instanceof Error ? err.message : 'failed to rename session');
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ export function RightRail({ projectId }: Props) {
|
||||
const [viewerFile, setViewerFile] = useState<{ path: string; content: string } | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// best-effort; ignore failure because localStorage may be unavailable (quota, private mode)
|
||||
try { localStorage.setItem(`${STORAGE_KEY}.open`, String(open)); } catch {}
|
||||
}, [open]);
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ import { useEffect, useRef, useState } from 'react';
|
||||
import type { Message, WsFrame } from '@/api/types';
|
||||
import { sessionEvents } from './sessionEvents';
|
||||
|
||||
// session_renamed frame removed from WsFrame — it was declared but never
|
||||
// published on the per-session WS channel (server publishes via broker.publishUser
|
||||
// since v1.4). chat_renamed remains; auto_name.ts publishes it on session WS.
|
||||
|
||||
interface State {
|
||||
messages: Message[];
|
||||
connected: boolean;
|
||||
@@ -118,14 +122,6 @@ function applyFrame(state: State, frame: WsFrame): State {
|
||||
messages: state.messages.filter((m) => !removeSet.has(m.id)),
|
||||
};
|
||||
}
|
||||
case 'session_renamed': {
|
||||
sessionEvents.emit({
|
||||
type: 'session_renamed',
|
||||
session_id: frame.session_id,
|
||||
name: frame.name,
|
||||
});
|
||||
return state;
|
||||
}
|
||||
case 'chat_renamed': {
|
||||
sessionEvents.emit({
|
||||
type: 'chat_updated',
|
||||
|
||||
@@ -40,7 +40,8 @@ export function useUserEvents(): void {
|
||||
};
|
||||
|
||||
ws.onerror = () => {
|
||||
// close handler will trigger reconnect
|
||||
// close handler will trigger reconnect; best-effort, ignore failure
|
||||
// because the socket may already be closing
|
||||
try { ws?.close(); } catch {}
|
||||
};
|
||||
};
|
||||
@@ -50,6 +51,7 @@ export function useUserEvents(): void {
|
||||
return () => {
|
||||
unmounted = true;
|
||||
if (reconnectTimer) clearTimeout(reconnectTimer);
|
||||
// best-effort cleanup; ignore failure because the socket may already be closed
|
||||
if (ws) try { ws.close(); } catch {}
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -38,9 +38,9 @@ export function Session() {
|
||||
if (cancelled) return;
|
||||
const p = projects.find((x) => x.id === s.project_id);
|
||||
if (p) setProject(p);
|
||||
}).catch(() => {});
|
||||
}).catch((err) => console.warn('Session: failed to load project for breadcrumb', err));
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch((err) => console.warn('Session: failed to fetch session', err));
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user