Errors
Understand DeepSeek SDK error types, inspect error details, and test authentication, configuration, timeout, and cancellation handling.
The SDK provides typed errors for common authentication, configuration, timeout, cancellation, and upstream failures. You can use instanceof to handle specific errors and isDeepSeekError() to identify errors belonging to the SDK. Some failures, including BatchAggregateError and certain native parsing errors, may be ordinary JavaScript errors.
Common error types
- `DeepSeekAuthenticationError` - Missing credentials or an HTTP 401 response. Fix the credentials before retrying.
- `DeepSeekAuthorizationError` - An HTTP 403 response indicating that the request is forbidden.
- `DeepSeekConfigurationError` - Invalid configuration or an unrecognized model when
unknownModel: "throw"is enabled. - `DeepSeekInvalidRequestError` - An HTTP 400 or 422 response indicating an invalid request.
- `DeepSeekRateLimitError` - An HTTP 429 response. May include
retryAfterMswhen the upstream service provides a retry hint. - `DeepSeekTimeoutError` - A request exceeds its configured timeout. Includes
timeoutMs. - `DeepSeekAbortError` - An operation is cancelled through an
AbortSignal. - `DeepSeekNetworkError` - A network failure prevents the request from completing.
- `DeepSeekApiError` - An upstream API error envelope is returned.
- `DeepSeekUpstreamError` - An upstream HTTP or transport failure.
- `DeepSeekProtocolError` - The response contains malformed or unexpected protocol data.
- `DeepSeekStructuredOutputError` - The response cannot be parsed or validated against the requested schema.
- `DeepSeekToolError` - Tool arguments, execution, or tool-call processing fails.
- `DeepSeekUnsupportedFeatureError` - The requested feature is unsupported by the current SDK method.
Retryability depends on the error and the active retry policy. Eligible transient failures may be retried, while authentication, configuration, and protocol errors generally require a fix rather than another attempt.
Error properties
name- Identifies the error class.code- Identifies the SDK error category.retryable- Indicates whether retrying may help.status- The HTTP status code, when available.details- Additional information about the failure.cause- The underlying error, when available.
Some error classes expose additional properties. For example, DeepSeekTimeoutError includes timeoutMs, DeepSeekRateLimitError may include retryAfterMs, and DeepSeekApiError exposes upstream error information through apiMessage and details.apiMessage.
Test error handling
The following executable example checks a normal request, missing credentials, an unknown model, a short timeout, and caller cancellation. It uses the same scenarios tested against the SDK. Timeout and cancellation tests depend on request timing, so a request that finishes before the trigger is reported as inconclusive.
DEEPSEEK_SESSION_ID=your_ds_session_id_valueDEEPSEEK_AUTHORIZATION=your_authorization_valueimport 'dotenv/config'; import { DeepSeekWeb, DeepSeekAuthenticationError, DeepSeekConfigurationError, DeepSeekTimeoutError, DeepSeekAbortError, isDeepSeekError,} from '@orcushq/deepseek'; const dsSessionId = process.env.DEEPSEEK_SESSION_ID;const authorization = process.env.DEEPSEEK_AUTHORIZATION; if (!dsSessionId || !authorization) { throw new Error( 'Set DEEPSEEK_SESSION_ID and DEEPSEEK_AUTHORIZATION in .env', );} const model = new DeepSeekWeb({ model: 'deepseek-v3', dsSessionId, authorization,}); function reportError(error: unknown): void { if (isDeepSeekError(error)) { console.log('Error class:', error.name); console.log('Error code:', error.code); console.log('Retryable:', error.retryable); console.log('HTTP status:', error.status); } else if (error instanceof Error) { console.log('Non-SDK error:', error.name, error.message); } else { console.log('Unknown error:', error); }} // Test 1: Normal requestasync function testNormalRequest() { console.log('\n--- Test 1: Normal request ---'); try { const response = await model.invoke( 'Reply with exactly: Error test passed.', ); console.log('Response:', response.content); console.log('PASS: Invocation succeeded.'); } catch (error) { reportError(error); }} // Test 2: Missing credentialsasync function testAuthenticationError() { console.log('\n--- Test 2: Missing credentials ---'); try { const unauthenticatedModel = new DeepSeekWeb({ model: 'deepseek-v3', dsSessionId: '', authorization: '', }); await unauthenticatedModel.invoke('Hello', { retry: false, }); console.log( 'UNEXPECTED: Request succeeded without credentials.', ); } catch (error) { if (error instanceof DeepSeekAuthenticationError) { console.log('PASS: Authentication error detected.'); } else { console.log('Unexpected error type:'); reportError(error); } }} // Test 3: Unknown modelasync function testConfigurationError() { console.log('\n--- Test 3: Unknown model ---'); try { const invalidModel = new DeepSeekWeb({ model: '__unknown_test_model__', unknownModel: 'throw', dsSessionId, authorization, }); await invalidModel.invoke('Hello', { retry: false, }); console.log( 'UNEXPECTED: Unknown model was accepted.', ); } catch (error) { if (error instanceof DeepSeekConfigurationError) { console.log('PASS: Configuration error detected.'); } else { console.log('Unexpected error type:'); reportError(error); } }} // Test 4: Very short timeoutasync function testTimeout() { console.log('\n--- Test 4: Timeout ---'); try { const response = await model.invoke('Reply with OK.', { timeoutMs: 1, retry: false, }); console.log( 'INCONCLUSIVE: Request completed before timeout.', response.content, ); } catch (error) { if (error instanceof DeepSeekTimeoutError) { console.log('PASS: Timeout error detected.'); console.log('Timeout:', error.timeoutMs, 'ms'); } else { console.log('Unexpected error type:'); reportError(error); } }} // Test 5: Caller cancellationasync function testCancellation() { console.log('\n--- Test 5: Cancellation ---'); const controller = new AbortController(); const timer = setTimeout(() => { controller.abort(); }, 100); try { const response = await model.invoke( 'Write a detailed essay about distributed systems.', { signal: controller.signal, retry: false, }, ); console.log( 'INCONCLUSIVE: Request completed before cancellation.', response.content, ); } catch (error) { if (error instanceof DeepSeekAbortError) { console.log('PASS: Cancellation detected.'); } else { console.log('Unexpected error type:'); reportError(error); } } finally { clearTimeout(timer); }} await testNormalRequest();await testAuthenticationError();await testConfigurationError();await testTimeout();await testCancellation();Run the file using your TypeScript runner. The normal request verifies successful invocation, while the other tests check whether the SDK produces the expected error class for each scenario.
npx tsx src/test-errors.tsHTTP error response bodies
The client-level or per-call includeErrorBody option controls whether a truncated upstream response body is included in HTTP-status error messages. It defaults to false. Enable it when debugging HTTP failures, and avoid logging credentials or sensitive response data.
HTTP 200 error envelopes
An HTTP 200 response can still contain an upstream error envelope. The SDK can throw `DeepSeekApiError` and expose the upstream message through `apiMessage` and `details.apiMessage`. `includeErrorBody` does not suppress this message.
Handling errors in applications
Use instanceof to handle errors your application expects, and isDeepSeekError() for other SDK-specific failures. Handle cancellation separately, inspect rate-limit hints when available, and rethrow unexpected errors rather than silently swallowing them.
Unknown-model fallback
With unknownModel: "fallback", an unrecognized model identifier resolves locally to deepseek-v3. Response metadata can report this through modelFellBack, fallbackReason, and fallbackNotice. This indicates the SDK fallback decision; it does not guarantee which exact model the upstream service served. Use unknownModel: "throw" when you want an unknown identifier to raise DeepSeekConfigurationError.