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

  1. Implement `connect(handle)` in the subclass so find()'s discovered handle is adopted
  2. Remove the `find()` override if the class doesn't need the acquisition flow
  3. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/e479602e07d65f77. Report an issue: GitHub.