Skip to content

Commit e2b777a

Browse files
committed
fix(agent-classifier): recognize 'Agent session error (subtype=…)' wrapper
The error classifier keyed on `agent_status=error_max_turns` (pipeline.py's wrapper) but missed runner.py:515's `Agent session error (subtype='error_max_turns')`. A real max-turns failure fell through to UNKNOWN → 'Unexpected error' (live-caught ABCA-483: a task hit the 100-turn cap but the Linear reply read 'Unexpected error'). The max_turns / max_budget / error_during_execution patterns now match BOTH the `agent_status=` and `subtype=` wrappers. Platform-agnostic, MAIN-BOUND (cherry-pick clean: single file + colocated test, no Linear/orchestration coupling).
1 parent 3af6cc3 commit e2b777a

2 files changed

Lines changed: 29 additions & 6 deletions

File tree

cdk/src/handlers/shared/error-classifier.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,17 @@ const PATTERNS: readonly ErrorPattern[] = [
210210
// ``Task did not succeed.*agent_status=`` catch-all so the concrete
211211
// cap / runtime-error signals surface to users rather than the
212212
// opaque "Agent task did not succeed" title. Each matches the
213-
// ``agent_status`` literals emitted by ``agent/src/pipeline.py``
214-
// (see ``_resolve_overall_task_status``) and
215-
// ``agent/src/runner.py``.
213+
// status literal under BOTH wrappers the agent emits:
214+
// - ``agent_status=error_max_turns`` — ``agent/src/pipeline.py``
215+
// (``_resolve_overall_task_status``); and
216+
// - ``Agent session error (subtype='error_max_turns')`` —
217+
// ``agent/src/runner.py:515`` (the terminal-error path).
218+
// Keying on only ``agent_status=`` missed the ``subtype=`` wrapper, so a
219+
// real max-turns failure fell through to UNKNOWN → "Unexpected error"
220+
// (live-caught on ABCA-483: a task hit the 100-turn cap but the reply
221+
// said "Unexpected error"). Match either ``agent_status=``/``subtype=``.
216222
{
217-
pattern: /agent_status=['"]?error_max_turns['"]?/i,
223+
pattern: /(?:agent_status|subtype)=['"]?error_max_turns['"]?/i,
218224
classification: {
219225
category: ErrorCategory.TIMEOUT,
220226
title: 'Exceeded max turns',
@@ -224,7 +230,7 @@ const PATTERNS: readonly ErrorPattern[] = [
224230
},
225231
},
226232
{
227-
pattern: /agent_status=['"]?error_max_budget_usd['"]?/i,
233+
pattern: /(?:agent_status|subtype)=['"]?error_max_budget_usd['"]?/i,
228234
classification: {
229235
category: ErrorCategory.TIMEOUT,
230236
title: 'Exceeded max budget',
@@ -234,7 +240,7 @@ const PATTERNS: readonly ErrorPattern[] = [
234240
},
235241
},
236242
{
237-
pattern: /agent_status=['"]?error_during_execution['"]?/i,
243+
pattern: /(?:agent_status|subtype)=['"]?error_during_execution['"]?/i,
238244
classification: {
239245
category: ErrorCategory.AGENT,
240246
title: 'Agent errored during execution',

cdk/test/handlers/shared/error-classifier.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,23 @@ describe('classifyError', () => {
256256
expect(result!.retryable).toBe(true);
257257
});
258258

259+
test('classifies the runner.py "Agent session error (subtype=...)" wrapper, not just agent_status= (K5, live-caught ABCA-483)', () => {
260+
// runner.py:515 emits ``Agent session error (subtype='error_max_turns')``
261+
// — a DIFFERENT wrapper from pipeline.py's ``agent_status=``. Pre-K5 this
262+
// fell through to UNKNOWN → "Unexpected error" even though the task hit the
263+
// 100-turn cap (live: a 1-line README task burned 101 turns, reply said
264+
// "Unexpected error"). The pattern must match the subtype= wrapper too.
265+
const turns = classifyError("Agent session error (subtype='error_max_turns')");
266+
expect(turns!.title).toBe('Exceeded max turns');
267+
expect(turns!.category).toBe(ErrorCategory.TIMEOUT);
268+
269+
const budget = classifyError("Agent session error (subtype='error_max_budget_usd')");
270+
expect(budget!.title).toBe('Exceeded max budget');
271+
272+
const exec = classifyError("Agent session error (subtype='error_during_execution')");
273+
expect(exec!.title).toBe('Agent errored during execution');
274+
});
275+
259276
test('matches agent_status with or without quotes around the literal', () => {
260277
// Defensive: the agent writer currently emits single-quoted
261278
// repr values (``agent_status='error_max_turns'``) but a future

0 commit comments

Comments
 (0)