Spinney propagates errors through the standard RxJS Observable contract. Any unhandled error during the crawl — a network failure, a parse error, or retry exhaustion — is forwarded to theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/cobyeastwood/spinney/llms.txt
Use this file to discover all available pages before exploring further.
error callback in your subscribe() call. On top of that, Spinney exposes a debug option for lightweight stderr logging and pause() / resume() methods that give you direct control over the batch processing loop.
Error callback
When a fatal error occurs inside_setUp() or httpXMLOrDocument(), Spinney calls this.subscriber.error(error). This delivers the error to the error handler you passed to subscribe() and terminates the Observable stream. Once a subscriber receives an error, the stream is in a terminal state and will not emit further next or complete events.
Debug mode
By default, Spinney uses a noop function as its internal error logger. Passingoptions.debug = true to the constructor replaces the noop with console.error(error?.message), which writes every caught error message to stderr. This happens inside catch blocks before the error is re-thrown or passed to subscriber.error(), so it does not interfere with your subscriber’s error handler — it only adds a side-effect log line.
HTTP error handling
Spinney distinguishes between HTTP error types and applies different strategies to each:| Scenario | Behavior |
|---|---|
| HTTP 404 | Promise.resolve() is returned immediately. The URL is skipped silently with no retry and no error emitted. |
| Other HTTP errors (5xx, 429, etc.) | The request is retried up to MAX_RETRIES (5) times. The Axios instance timeout grows by (retries * 1000) / 4 ms on each attempt. |
| Max retries reached | Throws Error('retries reached maximum' + retries). Caught by the outer try/catch, forwarded to subscriber.error(), and pause() is called. |
| robots.txt fetch failure | Caught in setUp(), debug?.() is called, and subscriber.error(error) is invoked. |
| Non-HTTP errors (DNS failure, connection refused, etc.) | Re-thrown immediately without retrying, caught by the outer handler, and forwarded to subscriber.error(). |
Pause and resume
spinney.pause() sets isProcessing = false. The internal batch loop in _setUp() checks this flag at the top of each iteration:
isProcessing is false the loop body is skipped, so no new HTTP requests are issued. spinney.resume() sets isProcessing = true, allowing the loop to continue on the next iteration.
pause() is called automatically in three situations: when subscriber.complete() is called (the crawl finished naturally), when the outer catch in httpXMLOrDocument() calls subscriber.error() (including after retry exhaustion), and in the Observable’s teardown function returned by setUp() (triggered by unsubscribe()).
Unsubscribing
subscribe() returns an RxJS Subscription. Calling subscription.unsubscribe() disconnects your observer from the Observable stream and triggers the teardown function returned by setUp(), which calls pause() to stop the batch loop.