Extends Error
EXPLICIT transient failure marker — "the operation failed for a temporary / unknown reason (network blip, lost response, exchange 5xx, rate limit); retry me".
The framework treats EVERY non-typed throw from the order gates and checks as the
"transient" verdict already — this class adds NO special handling and is NOT
pattern-matched anywhere in the framework by design. A plain throw new Error(...)
behaves identically. The class exists purely so application code states its intent
explicitly: a reader of the adapter sees "transient" spelled out instead of having
to know that unbranded throws default to it. Use it as the third leg of the triad:
Resolved as IBrokerOrderVerdict { reason: "transient" }
(see interfaces/Broker.interface):
onOrderOpenCommit type "active"/"schedule",
callbacks.onOrderSync, listenSync): the open is retried IDENTITY-STABLY —
the same signal row with the SAME signalId is re-submitted on the next tick
(event.attempt increments; the attempt is PRE-ARMED — persisted before the gate
call, so even a crash mid-attempt resumes with attempt >= 1), up to
CC_ORDER_OPEN_RETRY_ATTEMPTS. Tag exchange orders with clientOrderId = signalId
and RECONCILE at attempt > 0: query the prior order by that id BEFORE re-sending
and confirm the open if it filled. Do NOT rely on catching "duplicate" on re-send —
Binance's duplicate-clientOrderId guard only covers OPEN orders; an
instantly-filled market order will not dup.
Exhaustion drops the signal loudly AND signals exitEmitter (fatal: the network
would not let the engine work). With the config at 0 the retry slot is disabled:
a rejected open is dropped at once and the next tick regenerates a FRESH id.onOrderCloseCommit, same listeners): the position stays open
and the close is re-attempted on the next tick/candle (event.attempt
increments), up to CC_ORDER_CLOSE_RETRY_ATTEMPTS. Exhaustion FORCE-CLOSES the
engine state with the ORIGINAL closeReason + errorEmitter + exitEmitter
(the real exchange position must be reconciled by the adapter/operator).
With the config at 0 the cap is disabled: the close retries forever (legacy).onOrderActiveCheck / onOrderScheduleCheck,
callbacks.onOrderCheck, listenCheck): the failed ping is TOLERATED — the
order is assumed still open and monitoring continues (event.attempt
increments), up to CC_ORDER_CHECK_RETRY_ATTEMPTS CONSECUTIVE failures; a single
successful check resets the streak to 0. Exhaustion acts terminally (close
"closed" / cancel "user") + exitEmitter. With the config at 0 any failure is
terminal on the spot (legacy).exitEmitter after the
errorEmitter log) — unlike the typed terminal errors above, which are business
outcomes and never signal a process exit.attempt > 0 is therefore a HARD invariant even
across crashes: a prior order MAY have reached the exchange — reconcile first.
On restore the persisted counters are CLAMPED to 1: the reconcile bit survives,
the streak resets — a pre-crash outage never exhausts the budget on the first
post-restart attempt.__type__ === Symbol.for("OrderTransientError")
and the static guard exist for consistency with the other two errors (useful in
the application's own logging/metrics); the framework itself never checks it.constructor(message: string);
__type__: symbol
Runtime brand (Symbol.for — survives duplicated module instances)
static isOrderTransientError(error: object): boolean;
Nominal type guard by the runtime brand. Provided for symmetry with OrderRejectedError / OrderDeletedError (e.g. for application-side logging) — the framework itself does not branch on it: transient is the default verdict for ANY non-typed throw.
static fromError(error: object): OrderTransientError;
Nominal constructor for a new OrderTransientError from any thrown object. Use this
instead of instanceof to recognize instances created by a DIFFERENT copy of
this module (duplicated bundles, linked packages).