fix(apiproxy): name root export preparation failures

The pre-stream error boundary covers both the live-session flush barrier and the persistence read, but its response attributed every failure to reading storage. A flush failure therefore produced a misleading diagnostic even though the response correctly withheld private backend details.\n\nUse preparation as the shared operation name and cover the flush-failure path explicitly. Both preparation stages now retain one stable, path-safe HTTP 500 without pretending to identify the failing stage.
This commit is contained in:
Tianyi Cui
2026-08-11 17:47:13 +08:00
parent 5703ae356e
commit 8d63728584
2 changed files with 20 additions and 4 deletions

View File

@@ -3515,9 +3515,9 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro
signal.throwIfAborted()
} catch {
signal.throwIfAborted()
// Backend read failure: answer 500 without echoing the error, which
// may carry absolute host paths into the browser error bar.
return new Response('session log export failed to read the stored artifact', { status: 500 })
// Root preparation failure: answer 500 without echoing the error,
// which may carry absolute host paths into the browser error bar.
return new Response('session log export failed to prepare the stored artifact', { status: 500 })
}
if (root === undefined) {
return new Response('session not found', { status: 404 })

View File

@@ -392,7 +392,23 @@ describe('session.export download endpoint', () => {
)
expect(response.status).toBe(500)
const body = await response.text()
expect(body).toBe('session log export failed to read the stored artifact')
expect(body).toBe('session log export failed to prepare the stored artifact')
expect(body).not.toContain('/host/private/')
})
it('answers the private-error-safe 500 when the live root flush fails', async () => {
const api = await buildApi({ 'session-root': artifact('session-root') }, [], {
sessions: {
get: id => ({ id }),
flush: async () => { throw new Error('/host/private/flush-state') },
},
})
const response = await toFetchHandler(api).fetch(
new Request('http://host/api/session.export?sessionId=session-root'),
)
expect(response.status).toBe(500)
const body = await response.text()
expect(body).toBe('session log export failed to prepare the stored artifact')
expect(body).not.toContain('/host/private/')
})