mastra-ai/mastra · warning
The operation was aborted.
Error message
The operation was aborted.
What it means
The Reflector runner (which runs the Reflector agent that consolidates observations) defines its own module-level `withAbortCheck` helper that throws this error both before and after the wrapped operation if the caller's AbortSignal is aborted (reflector-runner.ts:158). Throwing at :158 means the signal was already aborted when the reflector step was about to run, so the library cancels reflection instead of executing a doomed model call.
Source
Thrown at packages/memory/src/processors/observational-memory/reflector-runner.ts:158
if (model) {
return model;
}
}
return undefined;
}
type ConcreteReflectionModel = Exclude<ResolvedReflectionConfig['model'], ModelByInputTokens>;
type ReflectionModelResolver = (inputTokens: number) => {
model: ConcreteReflectionModel;
selectedThreshold?: number;
routingStrategy?: 'model-by-input-tokens';
routingThresholds?: string;
};
async function withAbortCheck<T>(fn: () => Promise<T>, abortSignal?: AbortSignal): Promise<T> {
if (abortSignal?.aborted) throw new Error('The operation was aborted.');
const result = await fn();
if (abortSignal?.aborted) throw new Error('The operation was aborted.');
return result;
}
/**
* Minimum size of combined (buffered reflection + unreflected tail) expressed
* as a ratio of the regular threshold-activation target
* (reflectThreshold × (1 − bufferActivation)). Early TTL / provider-change
* triggers are suppressed if the post-activation size would fall below this
* floor — keeps early activations close to the system's tuned post-activation
* size while still letting them fire sooner than a threshold activation.
*/
const EARLY_ACTIVATION_SIZE_FLOOR_RATIO = 0.75;
/**
* Result of an attempt to activate a buffered reflection. The caller uses
* this to decide whether to fall through to sync reflection or backgroundView on GitHub (pinned to 75dd419e61)
Solutions
- Check `signal.aborted` before starting the memory pipeline and skip processing entirely rather than entering a phase that will throw.
- Give each phase its own AbortController (or use `AbortSignal.any` with only relevant sources) so an abort during Observer doesn't poison the Reflector phase entry.
- Extend timeouts to cover the full pipeline (observer + reflector), or run reflection asynchronously/detached from the request lifecycle so request cancellation doesn't abort it.
- Catch and treat this as benign cancellation in the memory-processing caller; optionally log token savings from the skipped reflection.
Example fix
// before
await agent.generate(messages, {
abortSignal: req.signal, // aborted during observer phase; reflector throws immediately
});
// after
const memoryController = new AbortController();
req.signal.addEventListener('abort', () => memoryController.abort(), { once: true });
// or run reflection detached:
void memory.process(messages, { abortSignal: memoryController.signal }).catch(err => {
if ((err as Error).message !== 'The operation was aborted.') console.error(err);
}); Defensive patterns
Strategy: try-catch
Validate before calling
if (signal?.aborted) {
// skip the memory pipeline entirely before the reflector phase can throw
return skipProcessing();
} Type guard
function isAbortError(err: unknown): err is Error {
return err instanceof Error && err.message === 'The operation was aborted.';
} Try / catch
try {
await runAgentWithMemory(input, { abortSignal: controller.signal });
} catch (err) {
if (isAbortError(err)) return; // cancelled before/during reflection; benign
throw err;
} Prevention
- Use a single AbortController owned by the pipeline so abort timing is deliberate.
- Budget timeouts for observer + reflector combined, not just one phase.
- Run reflection detached from request lifecycle when memory updates should survive cancellations.
- Check `signal.aborted` at phase boundaries and short-circuit gracefully.
When it happens
Trigger: The AbortSignal passed into memory processing is already aborted when the Reflector phase (`result`, which wraps its generation in `withAbortCheck`) begins — e.g. the request was cancelled during the preceding Observer phase, and the same signal is checked before reflection starts.
Common situations: Client disconnects or request timeout fires during the Observer phase, so by the time Reflector runs the shared signal is dead; reusing one AbortController across sequential memory phases; calling memory APIs with `AbortSignal.timeout` shorter than observer+reflector combined runtime; passing an already-settled request's signal.
Related errors
- The operation was aborted.
- Login cancelled
- Login cancelled
- CreateCancelledError (Operation cancelled)
- CreateCancelledError
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/408dbc88b95cbd97.
Report an issue: GitHub.