Skip to content

fix(runtime): explain harness-managed shell rejections - #2544

Open
aidandaly24 wants to merge 6 commits into
aws:refactorfrom
aidandaly24:fix/runtime-shell-harness
Open

aidandaly24 wants to merge 6 commits into
aws:refactorfrom
aidandaly24:fix/runtime-shell-harness

Conversation

@aidandaly24

@aidandaly24 aidandaly24 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Description

Keep rejected agentcore runtime shell connections inside the TUI and give HTTP 400 failures an actionable hint, including the case where a harness's backing Runtime was addressed directly.

  • Preserve the original SDK error, then show the conditional guidance on separate lines:
Screenshot 2026-10-06 at 7 54 57 PM
  • Retain connection failures in the TUI with retry, endpoint/back navigation, and quit. Keep completed-session exit and return-path behavior unchanged.
  • Share terminal handoff with the paired Harness shell command, while keeping the Runtime-specific hint in the Runtime handler.
  • Use the existing InputValidationError category and preserve the SDK exception as the cause.
  • Keep HTTP 403 errors and existing retries unchanged. No resource-name heuristics, extra discovery calls, new permissions, or hidden menu actions.

Harness shell support is provided by #2548. These PRs are intended to ship together: merge #2548 before this error message starts recommending the new command.

The HTTP 400/403 regression extends the existing non-retryable shell-opener test. The existing unexpected-failure screen test now covers the retained error, hint, retry, endpoint back navigation, and a subsequent successful attempt. No new test files or duplicate terminal test suite.

Related Issue

CLI v1 feedback, item 20. Paired with #2548; no separate GitHub issue was supplied.

Documentation PR

Not applicable. No commands, flags, or help text changed; the error includes the command alternative.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

Testing

How have you tested the change?

  • I ran bun test
  • I ran the relevant end-to-end tests with bun run test:e2e, or explained why they are not applicable
  • I ran bun run typecheck
  • I ran bun run lint:check
  • I ran bun run format:check
  • I ran bun run build
  • If I modified src/assets/, I updated affected snapshots with bun test <test-file> --update-snapshots and committed them (not applicable)

Results:

  • Observed the new HTTP 400 regression fail before the implementation.
  • bun test src/core/runtimeShell.test.ts src/handlers/runtime/shell: 28 pass, 0 fail.
  • Typecheck, lint, formatting, build, secrets scan, and git diff --check: pass.
  • Rebased onto refactor (133fb626); range-diff confirms the rebase did not change any patches.
  • Full bun test outside the restricted sandbox: 3,978 pass, 0 fail.
  • Live AWS TUI smoke using the Node distribution and --profile deploy: the existing demo harness's backing Runtime returned HTTP 400, the error and separated hint remained in the TUI, retry repeated the request, and Escape returned to the endpoint picker. No resources were created or modified.
  • The deployment E2E suite is not applicable: this fix does not change AWS requests, deployment, or shell transport behavior.

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly, or no new docs are needed
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published (requires feat(harness): add interactive shell command #2548 to ship the recommended command)

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.

@github-actions github-actions Bot added the size/s PR size: S label Oct 6, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress labels Oct 6, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Oct 6, 2026

@agentcore-devx-automation agentcore-devx-automation Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AgentCore Harness Review

Verdict: Looks good

Nice targeted improvement — turning the opaque Server rejected WebSocket connection: HTTP 400 into an actionable InputValidationError is a real UX win, and the suggested remediation command (agentcore harness exec --id <harness-id> --command <command>) matches the actual flag names in src/handlers/harness/exec/index.tsx.

Verified:

  • InputValidationError sets source: "user" and exitCode: 2 (ExitCode.USAGE), which the test asserts.
  • The SDK message string in bedrock-agentcore@0.4.3 (session.js:403) is produced exactly as Server rejected WebSocket connection: HTTP ${statusCode} with no trailing reason text, so the strict === comparison in runtimeShell.ts:80 matches today.
  • Tests mock at the createClient DI boundary rather than at fs/network internals — appropriate, not excessive.
  • The 403 branch continues to reject with the original error, preserving existing behavior.

One minor, non-blocking observation (ship as-is is fine):

  • src/core/runtimeShell.ts:80 uses exact string equality against the SDK error message. If a future SDK release appends a reason phrase or tweaks capitalization, this detection silently reverts to the old opaque behavior. A startsWith check or a small regex (similar in style to the existing RETRYABLE_UPGRADE) would be marginally more robust. Not required for this PR.

No telemetry gap here — this is an error-source refinement, and routing via AgentCoreCLIError.source is already how the root handler feeds telemetry.

@agentcore-devx-automation agentcore-devx-automation Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Oct 6, 2026
@github-actions github-actions Bot added size/s PR size: S and removed size/s PR size: S labels Oct 6, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Oct 6, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Oct 6, 2026
@aidandaly24
aidandaly24 marked this pull request as ready for review October 6, 2026 22:49
@github-actions github-actions Bot added size/m PR size: M and removed size/s PR size: S labels Oct 6, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Oct 6, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Oct 6, 2026
@aidandaly24
aidandaly24 force-pushed the fix/runtime-shell-harness branch from 5f661b7 to d2deecf Compare October 6, 2026 23:48
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Oct 6, 2026
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Oct 6, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Oct 6, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Oct 6, 2026
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Oct 6, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.82609% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.39%. Comparing base (133fb62) to head (d2deecf).

Files with missing lines Patch % Lines
src/components/ShellHandoff.tsx 97.05% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           refactor    #2544      +/-   ##
============================================
- Coverage     97.39%   97.39%   -0.01%     
============================================
  Files           642      644       +2     
  Lines         46910    46939      +29     
============================================
+ Hits          45689    45716      +27     
- Misses         1221     1223       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@notgitika notgitika left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is a much better experience than the bare HTTP 400 we had before. Left two comments that I think are worth fixing before this goes in

CI failing, can you rebase? It was fixed on the head of this branch.

await suspendTerminal(() => run({ stdin, stdout, stderr }));
} catch (caught) {
if (!(caught instanceof SilentCLIError)) {
setError(AgentCoreCLIError.fromError(caught));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this changes the exit code for failed shells. Before, any non-silent error went to exit(error), so renderTuiAt rejected and the CLI exited non-zero. Now we catch it, show it, and the only way out is ctrl+c, which calls exit() with no error (line 29). So e.g. agentcore runtime shell --id X with expired creds, or the very 400 this PR is about, ends up exiting 0, and telemetry logs it as a success.

The test "renderTuiAt propagates unexpected shell failures" was removed too, so nothing catches this anymore.

Maybe hang on to the caught error and pass it through on quit, something like if (key.ctrl && input === "c") exit(error ?? undefined), and the same for esc when there's no returnPath? Would be good to bring back a version of that test as well.

if (error.message !== "Server rejected WebSocket connection: HTTP 400") return undefined;
return (
"If this Runtime is managed by a harness, open its shell with:\n" +
"agentcore harness shell --id <harness-id>"

@notgitika notgitika Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agentcore harness shell doesn't exist on refactor yet. I think it's coming in #2548? If this merges first, the hint sends people to a command that isn't there. should be fine if our intention is to get the other one in first

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants