Skip to content

Commit 7128618

Browse files
committed
fix(#247): classify the claude Exec-format/broken-shim failure with retry guidance (ABCA-659)
When the agent image's claude CLI can't be exec'd (OSError Exec format error, or the shim's own 'claude native binary not installed'), the classifier had no matching pattern and fell through to the bare 'Unexpected error' with a generic 'report it' remedy — the exact no-guidance anti-pattern the error-feedback arc (K5 buckets, remedy+retryable+errorClass) was built to eliminate. Live-caught on ABCA-659's retry: the ❌ Linear comment just said 'Unexpected error', telling the user nothing about whether to retry or escalate. Add a COMPUTE + transient pattern so the failure reads honestly and actionably: 'Couldn't start the coding agent (environment issue) … not a problem with your request … reply here to try again; if every attempt fails the same way, the agent image needs a rebuild — contact your ABCA admin with the task id.' The transient class also lets the platform's session-start auto-retry take a shot. Matched before the AGENT/UNKNOWN fallthrough; two tests pin the copy + axis.
1 parent cb92466 commit 7128618

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,30 @@ const PATTERNS: readonly ErrorPattern[] = [
255255
errorClass: ErrorClass.TRANSIENT,
256256
},
257257
},
258+
{
259+
// The `claude` CLI on the agent image couldn't be exec'd: either the OS
260+
// refused the binary (`OSError: [Errno 8] Exec format error: 'claude'`) or
261+
// the claude-code shim reports its platform-native binary was never placed
262+
// ("claude native binary not installed" — its postinstall silently fell
263+
// back at image-build time). Live-caught on ABCA-659's retry: all 3 ECS runs
264+
// died at the run_agent step this way on a freshly rebuilt image, while the
265+
// native binary was present but unwired. This is an IMAGE/infra fault, NOT a
266+
// problem with the user's request — a fresh attempt usually lands on a host
267+
// that materializes the image cleanly; a persistent one is a bad build an
268+
// admin must rebuild. Without this bucket it fell through to a bare
269+
// "Unexpected error" with no guidance (the anti-pattern the error-feedback
270+
// work set out to kill). Matched before AGENT/UNKNOWN so the precise,
271+
// retry-oriented copy wins.
272+
pattern: /Exec format error.*claude|claude.*Exec format error|claude native binary not installed/i,
273+
classification: {
274+
category: ErrorCategory.COMPUTE,
275+
title: 'Couldn\'t start the coding agent (environment issue)',
276+
description: 'The agent runtime couldn\'t launch the `claude` CLI on the compute image — an infrastructure/image problem, not a problem with your request or code.',
277+
remedy: 'This is usually a transient image/compute hiccup. Reply here to try again — a fresh attempt typically clears it. If every attempt fails the same way, the agent image needs a rebuild: contact your ABCA admin with the task id above.',
278+
retryable: true,
279+
errorClass: ErrorClass.TRANSIENT,
280+
},
281+
},
258282

259283
// --- Agent ---
260284
{

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,27 @@ describe('classifyError', () => {
157157
expect(result!.retryable).toBe(true);
158158
});
159159

160+
test('classifies claude Exec-format / broken-shim as a transient image issue (ABCA-659, not "Unexpected error")', () => {
161+
// The raw run_agent failure the broken agent image produced.
162+
const result = classifyError(
163+
"Workflow run_agent step failed: OSError: [Errno 8] Exec format error: 'claude'",
164+
);
165+
expect(result!.category).toBe(ErrorCategory.COMPUTE);
166+
expect(result!.title).toBe('Couldn\'t start the coding agent (environment issue)');
167+
expect(result!.retryable).toBe(true);
168+
// MUST be transient so retryGuidance tells the user to just reply-to-retry
169+
// (and escalate to an admin only if it persists) — not the bare
170+
// "Unexpected error" with no guidance it used to fall through to.
171+
expect(result!.errorClass).toBe(ErrorClass.TRANSIENT);
172+
expect(result!.remedy).toMatch(/try again|rebuild|admin/i);
173+
});
174+
175+
test('classifies the claude shim self-report ("native binary not installed")', () => {
176+
const result = classifyError('Error: claude native binary not installed.');
177+
expect(result!.category).toBe(ErrorCategory.COMPUTE);
178+
expect(result!.errorClass).toBe(ErrorClass.TRANSIENT);
179+
});
180+
160181
test('classifies ECS exit without terminal status', () => {
161182
const result = classifyError(
162183
'ECS task exited successfully but agent never wrote terminal status after 5 polls',

0 commit comments

Comments
 (0)