Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/client/src/client/probeClassifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ function classifyNetworkError(error: unknown, context: ProbeClassifierContext):
}
return {
kind: 'error',
error: new SdkError(SdkErrorCode.EraNegotiationFailed, `Version negotiation probe failed: ${describeError(error)}`, {
error: new SdkError(SdkErrorCode.EraNegotiationFailed, `Version negotiation probe failed: ${describeError(error)}`, undefined, {
cause: error
})
};
Expand Down
2 changes: 1 addition & 1 deletion packages/client/test/client/probeAuthSeam.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,6 @@ describe('stamped-seam fault injection (identity-preserving auth outcomes, never
expect(out.settled).toBe('rejected');
expect(out.error).toBeInstanceOf(SdkError);
expect((out.error as SdkError).code).toBe(SdkErrorCode.EraNegotiationFailed);
expect(((out.error as SdkError).data as { cause?: unknown }).cause).toBe(netError);
expect((out.error as SdkError).cause).toBe(netError);
});
});
9 changes: 5 additions & 4 deletions packages/core-internal/src/errors/sdkErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,10 @@ export class SdkError extends Error {
constructor(
public readonly code: SdkErrorCode,
message: string,
public readonly data?: unknown
public readonly data?: unknown,
options?: ErrorOptions
) {
super(message);
super(message, options);
this.name = 'SdkError';
stampErrorBrands(this, new.target);
}
Expand Down Expand Up @@ -187,8 +188,8 @@ export class SdkHttpError extends SdkError {

declare readonly data: SdkHttpErrorData;

constructor(code: SdkErrorCode, message: string, data: SdkHttpErrorData) {
super(code, message, data);
constructor(code: SdkErrorCode, message: string, data: SdkHttpErrorData, options?: ErrorOptions) {
super(code, message, data, options);
this.name = 'SdkHttpError';
}

Expand Down
61 changes: 61 additions & 0 deletions packages/core-internal/test/errors/sdkErrorCause.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { describe, it, expect } from 'vitest';
import { SdkError, SdkErrorCode, SdkHttpError } from '../../src/index';

describe('SdkError cause chain', () => {
it('forwards cause to Error.cause when passed via options', () => {
const root = new TypeError('ENOTFOUND');
const error = new SdkError(SdkErrorCode.EraNegotiationFailed, 'probe failed', undefined, {
cause: root
});

expect(error.cause).toBe(root);
expect(error.data).toBeUndefined();
});

it('keeps data and cause independent', () => {
const root = new Error('connection refused');
const error = new SdkError(
SdkErrorCode.RequestTimeout,
'timed out',
{ timeout: 5000 },
{
cause: root
}
);

expect(error.cause).toBe(root);
expect(error.data).toEqual({ timeout: 5000 });
});

it('leaves cause undefined when options are omitted', () => {
const error = new SdkError(SdkErrorCode.NotConnected, 'not connected');
expect(error.cause).toBeUndefined();
});

it('leaves cause undefined when only data is passed', () => {
const error = new SdkError(SdkErrorCode.RequestTimeout, 'timed out', { timeout: 5000 });
expect(error.cause).toBeUndefined();
});
});

describe('SdkHttpError cause chain', () => {
it('forwards cause through to Error.cause', () => {
const root = new Error('socket hang up');
const error = new SdkHttpError(
SdkErrorCode.ClientHttpFailedToOpenStream,
'stream failed',
{ status: 502, statusText: 'Bad Gateway' },
{ cause: root }
);

expect(error.cause).toBe(root);
expect(error.status).toBe(502);
expect(error.data.status).toBe(502);
});

it('leaves cause undefined when options are omitted', () => {
const error = new SdkHttpError(SdkErrorCode.ClientHttpAuthentication, 'auth failed', { status: 401 });

expect(error.cause).toBeUndefined();
});
});
Loading