mastra-ai/mastra · error
${this.constructor.name}: find() requires connect() to adopt
Error message
${this.constructor.name}: find() requires connect() to adopt the handle it returns. What it means
The MastraSandbox base constructor enforces that acquisition primitives are implemented in pairs: if a subclass defines `find()` (to locate an existing running sandbox) as part of the create/find/connect acquisition flow, it must also define `connect()` to adopt the handle that find() returns. A find() without connect() would let a handle be discovered but never adopted, so the sandbox would falsely report `outcome: 'connected'` while operating on nothing.
Source
Thrown at packages/core/src/workspace/sandbox/mastra-sandbox.ts:273
this._onStop = options.onStop;
this._onDestroy = options.onDestroy;
this.#env = { ...options.env };
// Shadow start() with the lifecycle wrapper (same pattern as
// SandboxProcessManager) so DIRECT start() calls get the same coalescing,
// status handling, and onStart hook as `_start()`/`ensureRunning()`.
const hasStartOverride = this.start !== MastraSandbox.prototype.start;
this._implStart = this.start.bind(this);
this.start = () => this._start();
// Rung selection: a subclass `start()` override wins; otherwise the
// primitives drive acquisition when `create()` is implemented. Anything
// declared as a class field is invisible here and lands on the base
// `start()`, which throws.
this._useAcquisitionPrimitives = !hasStartOverride && typeof this.create === 'function';
// A handle nobody adopts would still report `outcome: 'connected'`, so the
// sandbox would look reconnected while running against nothing.
if (this._useAcquisitionPrimitives && typeof this.find === 'function' && typeof this.connect !== 'function') {
throw new Error(`${this.constructor.name}: find() requires connect() to adopt the handle it returns.`);
}
// Automatically create MountManager if subclass implements mount()
if (this.mount) {
this.mounts = new MountManager({
mount: this.mount.bind(this),
logger: this.logger,
});
}
// Wire up process manager if provided
if (options.processes) {
const pm = options.processes;
// Set the sandbox back-reference. The process manager reads this
// lazily (at call time), so it's fine that the subclass constructor
// hasn't finished yet.
pm.sandbox = this;
this.processes = pm;View on GitHub (pinned to 75dd419e61)
Solutions
- Implement `connect(handle)` in the subclass so find()'s discovered handle is adopted
- Remove the `find()` override if the class doesn't need the acquisition flow
- If you intended no acquisition primitives, override `start()` instead so the pair check is skipped
Example fix
// before
class RemoteSandbox extends MastraSandbox {
async find() { return probeExisting(); }
// connect() missing -> constructor throws
}
// after
class RemoteSandbox extends MastraSandbox {
async find() { return probeExisting(); }
async connect(handle) { this._handle = handle; await this.attach(handle); }
} Defensive patterns
Strategy: type-guard
Validate before calling
type AcquisitionSandbox = { find: unknown } & { connect: (h: unknown) => Promise<unknown> };
function hasBalancedAcquisition(s: object): s is AcquisitionSandbox {
const hasFind = 'find' in s && typeof (s as any).find === 'function';
const hasConnect = 'connect' in s && typeof (s as any).connect === 'function';
return !hasFind || hasConnect;
} Type guard
function definesAcquisitionPair(ctor: new (...a: any[]) => object): boolean {
const proto = ctor.prototype as Record<string, unknown>;
const hasFind = typeof proto.find === 'function';
const hasConnect = typeof proto.connect === 'function';
return !hasFind || hasConnect;
} Try / catch
try {
sandbox = new RemoteSandbox(opts);
} catch (err) {
if (/find\(\) requires connect\(\)/.test(String(err?.message))) {
throw new Error(`${RemoteSandbox.name}: implement connect() to adopt find()'s handle, or remove find()`);
}
throw err;
} Prevention
- Add a compile-time check: `type MustImplementConnect = find extends () => any ? connect : never`
- Write a unit test that instantiates every sandbox subclass to catch contract violations at CI time
- When implementing the acquisition flow, scaffold find/connect/create together, never separately
When it happens
Trigger: Subclassing MastraSandbox and overriding `find()` (without overriding `start()`, which would disable acquisition primitives) while not implementing `connect()`; typically a partial or in-progress implementation of the acquisition protocol.
Common situations: Implementing a custom remote/container sandbox that reuses existing instances; refactoring that removed connect() but left find(); copying a partial example subclass.
Related errors
- ${this.constructor.name} implements neither start() nor the
- MemoryThread.${methodName}() requires an agentId. Pass it vi
- Unhandled content part type: ${(exhaustiveCheck as { type: s
- execa is not available in Cloudflare Workers
- Sandbox provider "${sandbox.provider}" does not support netw
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e479602e07d65f77.
Report an issue: GitHub.