Skip to content

fix(e2b): improve envd process client error handling and parsing#2196

Open
chcodex wants to merge 2 commits into
agentscope-ai:mainfrom
chcodex:fix/e2b-envd-client
Open

fix(e2b): improve envd process client error handling and parsing#2196
chcodex wants to merge 2 commits into
agentscope-ai:mainfrom
chcodex:fix/e2b-envd-client

Conversation

@chcodex

@chcodex chcodex commented Jul 14, 2026

Copy link
Copy Markdown

Summary

Fix E2B envd process.Process/Start server-streaming response parsing to correctly handle the Connect protocol Enveloped-Message frame format and proto3 scalar field semantics.

Root Cause

sint32 exit_code = 1 is a regular proto3 scalar field (not proto3_optional, not oneof). When exit code is 0, the field is omitted from both protobuf binary wire format and JSON output (proto3 default-value omission). The original code used DynamicMessage.hasField() to check presence — returns false for default values — causing exit code 0 to be treated as "no exit code received", resulting in exitCode = -2147483648 (Integer.MIN_VALUE).

Changes

# Change Evidence
1 EndStreamResponse (flags & 0x02) — parse as JSON EndStreamMessage, throw on error, break cleanly on success Connect Protocol Spec §Streaming-Response – bit 1 / Python SDK ServerStreamParser
2 Compressed frames (flags & 0x01) — throw explicit IOException Connect spec – bit 0
3 Reserved bits (flags & 0xFC) — skip Connect spec – 6 MSBs reserved
4 Proto3 scalar getField — replace hasField()+getField() with getField() for exit_code Proto3 defaults / Python SDK event.event.end.exit_code
5 EndEvent.error to stderr — write when present (signal-killed processes) Go handler / Python SDK command_handle.py#L115
6 JSON end event fix — always set end when JSON node exists; also parse error field Python SDK uses JSON codec and reads event.event.end.error directly
7 Length mask removed& 0x7FFFFFFF stripped Connect spec — Message-Length is 4-byte unsigned int
8 Evidence comments — references added inline to Connect spec, Python SDK, Go handler, Proto3 docs Each code location links to its authoritative source

Tests

Unit Tests (E2bEnvdProcessClientTest) — 14 tests, 0 failures

Existing: codec selection, frame parsing, malformed base64, missing-end sentinel, single end frame.

New (7):

Test Verifies
endStreamResponseWithErrorThrows flags=0x02 with error JSON → SandboxRuntimeException
endStreamResponseWithoutErrorBreaksCleanly data frame + EndStreamResponse {} → clean break
exitCodeZeroDefaultWhenOmitted end:{} (exitCode omitted) → exit=0 (proto3 default via getField)
exitCodeNonZero end:{exitCode:42} → exit=42
endEventErrorWrittenToStderr end:{error:"signal: 9"} → stderr contains error
compressedFrameThrowsIOException flags=0x01 → IOException
reservedFlagsFrameIsSkipped flags=0x04 → skipped, normal events processed

Integration Tests (E2bEnvdProcessClientIntegrationTest) — 2 tests (require real sandbox + -DE2B_API_KEY)

Test Verifies
captureRawConnectFrames Raw Connect protocol frame flags from real server (bit 1 set on EndStream)
signalKillViaRunShell Thread A runs sleep 120 via runShell; Thread B kills via killall; verifies EndEvent.error="signal: killed" captured to stderr through drainStartStream pipeline

Test Plan

# Unit tests (no external dependencies)
mvn test -pl agentscope-extensions/agentscope-extensions-sandbox/agentscope-extensions-sandbox-e2b -am

# Integration tests (requires E2B API key)
mvn test -pl agentscope-extensions/agentscope-extensions-sandbox/agentscope-extensions-sandbox-e2b \
  -DE2B_API_KEY=<key> -DE2B_TEMPLATE_ID=code-interpreter-v1

@chcodex chcodex requested a review from a team July 14, 2026 08:35
@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.04651% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...e/extensions/sandbox/e2b/E2bEnvdProcessClient.java 86.04% 3 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

@jujn

jujn commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Suggest supplementary test

@AgentScopeJavaBot AgentScopeJavaBot added bug Something isn't working area/extensions agentscope-extensions (general) labels Jul 14, 2026

@AgentScopeJavaBot AgentScopeJavaBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 AI Review

This PR improves the Connect protocol frame parsing in E2bEnvdProcessClient by properly handling end-stream frames (flag 0x02), compressed frames (flag 0x01), and unknown flags — replacing the previous naive flags != 0x00 check. It also adds SLF4J debug logging for better diagnosability and a clean parseEndStreamResponse() / EndStreamMessage record for end-stream error parsing. The changes are well-scoped and align with the Connect protocol specification. A few minor robustness gaps were identified around defensive null handling and a silently-swallowed exception that should be addressed for consistency with the new logging additions.

(inline comments could not be attached — line numbers fell outside PR hunks. See archived report.)

@AgentScopeJavaBot AgentScopeJavaBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 AI Review

This PR improves the Connect protocol frame parsing in E2bEnvdProcessClient by properly handling end-stream frames (flag 0x02), compressed frames (flag 0x01), and unknown flags — replacing the previous naive flags != 0x00 check. It also adds SLF4J debug logging for better diagnosability and a clean parseEndStreamResponse() / EndStreamMessage record for end-stream error parsing. The changes are well-scoped and align with the Connect protocol specification. A few minor robustness gaps were identified around defensive null handling and a silently-swallowed exception that should be addressed for consistency with the new logging additions.

(inline comments could not be attached — line numbers fell outside PR hunks. See archived report.)

- Parse EndStreamResponse (flags & 0x02) per Connect protocol spec
- Use getField() instead of hasField() for proto3 scalar exit_code
  - Proto3 omits default values (0) from wire; getField() returns default
- Extract EndEvent.error to stderr (signal-killed processes)
- Fix JSON codec: always set end event when end node exists
  - Parsed error field from JSON (proto3_optional)
- Reject compressed frames (flags & 0x01) with explicit error
- Skip reserved flag bits (flags & 0xFC)
- Add debug logging for frame processing diagnostics
- Add 7 unit tests covering exit_code=0, EndStreamResponse, error field
- Add integration test: signal-killed process via runShell + threads
- Add evidence comments referencing Connect spec, Python SDK, Go handler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/extensions agentscope-extensions (general) bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants