UpstashRedis Errors - TundraSoft/tundra-connect GitHub Wiki
UpstashRedis throws UpstashRedisError for local request validation and
vendor responses — see errors/Base.ts and
errors/UpstashRedisErrorCodes.ts.
import {
UpstashRedisError,
UpstashRedisErrorCodes,
} from '@tundraconnect/upstash-redis/errors';
const error = new UpstashRedisError('SERVICE_UNAVAILABLE', { status: 503 });
console.log(error.message);| Code | Meaning |
|---|---|
UNKNOWN_ERROR |
An unmapped HTTP status was returned, or an unknown code was supplied to the constructor. |
CONFIG_INVALID_TOKEN |
auth is missing, isn't type: 'BEARER', or its token is blank/not a string. Thrown at construction time. |
REQUEST_VALIDATION_ERROR |
A command array (built internally, or passed to execute()/pipeline()) failed local Guardian validation and was never sent — error.cause is a GuardianError. |
INVALID_REQUEST |
A local business-rule check failed before any request was sent — SET's ex+px or nx+xx both set, or an empty key/value/field list for del/exists/hset/lpush/rpush. Carries the reason in error.getContextValue('reason'). |
AUTH_FAILED |
UpstashRedis returned HTTP 401 — the Bearer token is missing or invalid. |
COMMAND_ERROR |
UpstashRedis returned HTTP 400. Upstash uses this single status for both a malformed request and a Redis command that failed (e.g. "ERR wrong number of arguments for 'get' command") — there is no separate status to tell the two apart, so this connect doesn't invent one either. The vendor's raw message is in error.getContextValue('reason'). |
METHOD_NOT_ALLOWED |
UpstashRedis returned HTTP 405 (only HEAD/GET/POST/PUT are supported). |
RESPONSE_ERROR |
A success response's body failed schema validation. |
SERVICE_UNAVAILABLE |
UpstashRedis returned a 5xx status. |
TIMEOUT |
Upstash did not answer within the client timeout (timeoutSeconds in context). |
NETWORK_ERROR |
fetch failed before any response (DNS, TLS, connection reset); the transport error is the cause. |
Upstash's own documentation describes 400 Bad Request as covering both
"a syntax error, an invalid/unsupported command is sent" and "command
execution fails" — the same status, the same {"error": "..."} envelope,
for both a malformed request and a Redis-level command error (verified
directly against the vendor's docs). Since there's no way to reliably
tell them apart from the HTTP layer, COMMAND_ERROR covers both, with the
vendor's message attached for whoever needs to distinguish them by
reading it.
The resolved code is also available as a public, readonly error.code
property — branch on failure mode without matching against .message:
try {
await client.get('foo');
} catch (error) {
if (error instanceof UpstashRedisError && error.code === 'COMMAND_ERROR') {
console.error(
'Redis rejected the command:',
error.getContextValue('reason'),
);
}
}Use getContextValue() to read diagnostic metadata — see
errors/Base.ts. The configured Bearer token is never
included in any thrown error's message or context.
TIMEOUT, NETWORK_ERROR, SERVICE_UNAVAILABLE and RATE_LIMITED mean
"no answer yet": retrying later can help. Every other code is a definite
refusal or a misconfiguration that retrying will not fix. Branch on the
readonly err.transient, which is true for exactly these four, rather
than listing codes yourself. The set is also exported as
UPSTASH_REDIS_TRANSIENT_CODES from @tundraconnect/upstash-redis/errors.
import { UpstashRedisError } from '@tundraconnect/upstash-redis/errors';
declare function callTheClient(): Promise<unknown>;
try {
await callTheClient();
} catch (err) {
if (err instanceof UpstashRedisError && err.transient) {
// queue it and try again later
}
throw err;
}| Context | Present on | Meaning |
|---|---|---|
timeoutSeconds |
TIMEOUT |
The deadline that was missed, in seconds. |
A rate-limited request throws RATE_LIMITED. Two context values tell you what to
do next:
| Context | Meaning |
|---|---|
retryAfterSeconds |
Seconds the vendor asked you to wait, parsed by RESTler from Retry-After (delta seconds or an HTTP-date), X-RateLimit-Reset-After, RateLimit-Reset, or an epoch-seconds X-RateLimit-Reset. undefined when the response carried none — never a guess. |
retried |
Set only when maxRetryWait is configured: true if RESTler already waited once and was throttled again, false if it did not wait (the hint exceeded the cap, or there was no hint to wait on). |
Nothing is retried by default. Opt in with two client options (seconds,
each 0–120):
-
maxRetryWait— when a 429 carries a hint no longer than this, RESTler waits that long and retries once; otherwise it throwsRATE_LIMITEDimmediately.0disables the retry. -
defaultRetryWait— the wait used when a 429 carries no hint. Without it a hintless 429 is never retried: RESTler does not invent a delay. Only consulted whenmaxRetryWaitis set, and still capped by it.
| Code | Raised when |
|---|---|
RATE_LIMITED |
HTTP 429. Read retryAfterSeconds from the error context and back off; never retry immediately. |