Improve workflow error messaging

This commit is contained in:
2026-03-09 23:51:37 -04:00
parent fa2de3e259
commit f2c25fb9c6
11 changed files with 272 additions and 41 deletions

View File

@@ -202,8 +202,8 @@ describe('task repos', () => {
resource_key: 'index_search:ticker:AAPL'
});
await tasksRepo.markTaskFailure(failedTask.id, 'Embedding request failed', 'failed', {
detail: 'Embedding request failed',
await tasksRepo.markTaskFailure(failedTask.id, 'Search indexing could not generate embeddings for AAPL · doc-2. The AI provider returned an empty response.', 'search.embed', {
detail: 'Embedding generation failed.',
context: {
progress: { current: 2, total: 5, unit: 'sources' },
counters: { chunksEmbedded: 20 },
@@ -216,7 +216,9 @@ describe('task repos', () => {
expect(completed?.stage_detail).toContain('Analysis report generated');
expect(completed?.stage_context?.subject?.ticker).toBe('AAPL');
expect(failed?.stage_detail).toBe('Embedding request failed');
expect(failed?.stage).toBe('search.embed');
expect(failed?.stage_detail).toBe('Embedding generation failed.');
expect(failed?.error).toContain('Search indexing could not generate embeddings');
expect(failed?.stage_context?.progress?.current).toBe(2);
});
});

View File

@@ -406,11 +406,13 @@ export async function markTaskFailure(
export async function setTaskStatusFromWorkflow(
taskId: string,
status: TaskStatus,
error?: string | null
error?: string | null,
detail?: string | null
) {
const isTerminal = status === 'completed' || status === 'failed';
const nextStage = statusToStage(status);
const nextError = status === 'failed' ? (error ?? 'Workflow run failed') : null;
const nextDetail = nextStatusDetail(status, nextError, detail);
return await db.transaction(async (tx) => {
const [current] = await tx
@@ -426,7 +428,7 @@ export async function setTaskStatusFromWorkflow(
const hasNoStateChange = current.status === status
&& current.stage === nextStage
&& (current.error ?? null) === nextError
&& (current.stage_detail ?? null) === (nextStatusDetail(status, nextError) ?? null)
&& (current.stage_detail ?? null) === (nextDetail ?? null)
&& (current.stage_context ?? null) === null
&& (isTerminal ? current.finished_at !== null : current.finished_at === null);
@@ -440,7 +442,7 @@ export async function setTaskStatusFromWorkflow(
.set({
status,
stage: nextStage,
stage_detail: nextStatusDetail(status, nextError),
stage_detail: nextDetail,
stage_context: null,
error: nextError,
updated_at: now,
@@ -506,9 +508,9 @@ export async function updateTaskNotificationState(
return row ? toTask(row) : null;
}
function nextStatusDetail(status: TaskStatus, error?: string | null) {
function nextStatusDetail(status: TaskStatus, error?: string | null, detail?: string | null) {
if (status === 'failed') {
return error ?? 'Workflow run failed';
return detail ?? error ?? 'Workflow run failed';
}
if (status === 'completed') {