Skip to content

Comments

sdk: properly reject pending agent-ready promises and surface structured server errors#388

Merged
willwashburn merged 3 commits intofix/sdk-standalone-spawn-defaultsfrom
copilot/sub-pr-387
Feb 8, 2026
Merged

sdk: properly reject pending agent-ready promises and surface structured server errors#388
willwashburn merged 3 commits intofix/sdk-standalone-spawn-defaultsfrom
copilot/sub-pr-387

Conversation

Copy link

Copilot AI commented Feb 8, 2026

Addresses review feedback on PR #387: clearPendingAgentReady() was leaving promises hanging forever instead of rejecting them, and onError callback was passing generic errors without structured context from the daemon.

Changes

  • Replace clearPendingAgentReady() with proper rejection: Changed to rejectPendingAgentReady(err) so callers receive errors instead of permanently pending promises

  • Surface structured server errors: Created RelayServerError class with code, fatal, and envelope fields. Updated onError callback to pass this instead of generic Error:

    client.onError = (error: Error) => {
      if (error instanceof RelayServerError) {
        console.log(`Server error [${error.code}]:`, error.message);
        if (error.fatal) {
          // Handle fatal errors differently
        }
      }
    };
  • Fix unhandled rejections in spawn: Added error handling when spawn fails with waitForReady: true to suppress unhandled rejection from the internal readyPromise

  • Add test coverage: New test validates onError callback receives RelayServerError with all structured fields


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.


Open with Devin

Copilot AI and others added 2 commits February 8, 2026 20:44
…layServerError with structured context, add onError test, handle unhandled rejections

Co-authored-by: willwashburn <957608+willwashburn@users.noreply.github.com>
Co-authored-by: willwashburn <957608+willwashburn@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix fail-fast behavior when spawn manager is disabled sdk: properly reject pending agent-ready promises and surface structured server errors Feb 8, 2026
Copilot AI requested a review from willwashburn February 8, 2026 20:46
@willwashburn willwashburn marked this pull request as ready for review February 8, 2026 21:27
@willwashburn willwashburn merged commit 0bc1375 into fix/sdk-standalone-spawn-defaults Feb 8, 2026
1 check passed
@willwashburn willwashburn deleted the copilot/sub-pr-387 branch February 8, 2026 21:28
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

⚠️ 1 issue in files not directly in the diff

⚠️ RelayServerError not exported from SDK main entry point (packages/sdk/src/index.ts:176-184)

The new RelayServerError class is defined in packages/sdk/src/errors.ts and used internally by client.ts, but it is not exported from packages/sdk/src/index.ts. All other error classes (RelayError, DaemonNotRunningError, AgentNotFoundError, etc.) are exported from the main entry point at packages/sdk/src/index.ts:176-184, but RelayServerError is missing.

Impact on SDK consumers

The PR description shows the intended usage pattern:

client.onError = (error: Error) => {
  if (error instanceof RelayServerError) {
    console.log(`Server error [${error.code}]:`, error.message);
  }
};

Consumers importing from @agent-relay/sdk (the standard import path) will not have access to RelayServerError. They would need to know to use the deep import @agent-relay/sdk/errors instead, which is inconsistent with how all other error types are exported. This makes the new structured error feature effectively undiscoverable for most users.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment on lines +22 to +34
export class RelayServerError extends RelayError {
code: string;
fatal: boolean;
envelope?: any;

constructor(message: string, code: string, fatal: boolean, envelope?: any) {
super(message);
this.name = 'RelayServerError';
this.code = code;
this.fatal = fatal;
this.envelope = envelope;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 Duplicate RelayServerError class definitions cause instanceof failures across packages

RelayServerError is defined as two separate classes: one in packages/utils/src/errors.ts:58-70 and another in packages/sdk/src/errors.ts:22-34. The SDK's client.ts imports from ./errors.js (the SDK-local copy), but @agent-relay/utils/errors also exports its own RelayServerError.

Root Cause and Impact

The established pattern in this codebase is that @agent-relay/utils/errors is the "single source of truth" for error classes (as stated in the file header comments at packages/sdk/src/errors.ts:4-6). All other error classes in the SDK's errors.ts are re-exported from @agent-relay/utils/errors. However, RelayServerError breaks this pattern by being defined locally in the SDK while also being added to @agent-relay/utils/errors.

Because these are two distinct JavaScript class constructors, instanceof checks will fail when comparing across packages. For example, if any code in the @agent-relay/utils or @agent-relay/daemon packages creates a RelayServerError using their import from @agent-relay/utils/errors, and SDK consumer code checks error instanceof RelayServerError using the SDK's version, the check will return false.

The SDK's errors.ts should re-export RelayServerError from @agent-relay/utils/errors instead of defining its own copy, consistent with how all other error classes are handled.

Prompt for agents
Remove the local RelayServerError class definition from packages/sdk/src/errors.ts (lines 19-34) and instead re-export it from @agent-relay/utils/errors, consistent with how all other error classes are handled. Change the export block at lines 9-17 to include RelayServerError:

export {
  RelayError,
  DaemonNotRunningError,
  AgentNotFoundError,
  TimeoutError,
  ConnectionError,
  ChannelNotFoundError,
  SpawnError,
  RelayServerError,
} from '@agent-relay/utils/errors';

Also remove the now-unnecessary local import of RelayError on line 20 and the entire local class definition on lines 22-34.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants