Skip to content

Commit 884a194

Browse files
committed
fix(feedback): preserve full Error object through outcome and state
Per Hweinstock's review feedback. Was stringifying errors to .message at the boundary in handleFeedback and useFeedbackFlow, which discarded the stack/cause. Keeping the Error around lets callers retain that info and narrow with instanceof when they want; we still pull .message at the final UI render boundary.
1 parent ffbb0fe commit 884a194

5 files changed

Lines changed: 11 additions & 10 deletions

File tree

src/cli/commands/feedback/action.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export type FeedbackOutcome =
77
| { kind: 'submitted'; result: FeedbackSubmissionResult }
88
| { kind: 'declined' }
99
| { kind: 'no-tty' }
10-
| { kind: 'error'; error: string };
10+
| { kind: 'error'; error: Error };
1111

1212
export async function handleFeedback(message: string, options: FeedbackOptions): Promise<FeedbackOutcome> {
1313
const consent = await promptForConsent();
@@ -23,7 +23,6 @@ export async function handleFeedback(message: string, options: FeedbackOptions):
2323
});
2424
return { kind: 'submitted', result };
2525
} catch (err) {
26-
const error = err instanceof Error ? err.message : String(err);
27-
return { kind: 'error', error };
26+
return { kind: 'error', error: err instanceof Error ? err : new Error(String(err)) };
2827
}
2928
}

src/cli/commands/feedback/command.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export const registerFeedback = (program: Command) => {
4949
throw new Error('Feedback consent must be confirmed interactively. Re-run agentcore feedback in a TTY.');
5050
}
5151
if (outcome.kind === 'error') {
52-
throw new Error(outcome.error);
52+
throw outcome.error;
5353
}
5454
if (outcome.kind === 'declined') {
5555
if (options.json) {

src/cli/tui/screens/feedback/FeedbackScreen.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,7 @@ export function FeedbackScreen({ initialScreenshot, onExit }: FeedbackScreenProp
154154
);
155155
}
156156

157-
return <ErrorPrompt message="Failed to submit feedback." detail={state.error} onBack={retry} onExit={onExit} />;
157+
return (
158+
<ErrorPrompt message="Failed to submit feedback." detail={state.error?.message} onBack={retry} onExit={onExit} />
159+
);
158160
}

src/cli/tui/screens/feedback/__tests__/useFeedbackFlow.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const Harness = React.forwardRef<HarnessHandle, HarnessProps>((props, ref) => {
4343
<Text>
4444
phase:{flow.state.phase} message:{flow.state.message || '<empty>'} screenshot:
4545
{flow.state.screenshotPath ?? '<none>'} error:
46-
{flow.state.error ?? '<none>'} inputError:{flow.state.inputError ?? '<none>'}
46+
{flow.state.error?.message ?? '<none>'} inputError:{flow.state.inputError ?? '<none>'}
4747
</Text>
4848
);
4949
});
@@ -178,7 +178,7 @@ describe('useFeedbackFlow', () => {
178178
act(() => ref.current!.flow.confirmConsent());
179179
await flushAsync();
180180
expect(ref.current!.flow.state.phase).toBe('error');
181-
expect(ref.current!.flow.state.error).toBe('HTTP 500');
181+
expect(ref.current!.flow.state.error?.message).toBe('HTTP 500');
182182

183183
act(() => ref.current!.flow.retry());
184184
await flushAsync();

src/cli/tui/screens/feedback/useFeedbackFlow.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ export interface FeedbackState {
1717
message: string;
1818
screenshotPath?: string;
1919
result?: FeedbackSubmissionResult;
20-
/** Submission failure detail, shown on the 'error' phase. */
21-
error?: string;
20+
/** Submission failure detail, shown on the 'error' phase. Preserved as Error so callers retain stack/cause. */
21+
error?: Error;
2222
/** Inline validation error shown on the current input phase. */
2323
inputError?: string;
2424
}
@@ -110,7 +110,7 @@ export function useFeedbackFlow(options: UseFeedbackFlowOptions = {}) {
110110
if (result.success) {
111111
setState(prev => ({ ...prev, phase: 'success', result: result.submission }));
112112
} else {
113-
setState(prev => ({ ...prev, phase: 'error', error: result.error.message }));
113+
setState(prev => ({ ...prev, phase: 'error', error: result.error }));
114114
}
115115
}, [onSubmit, state.message, state.screenshotPath]);
116116

0 commit comments

Comments
 (0)