paperclipai/paperclip · error

Sandbox driver does not support duplex channels for this lea

Error message

Sandbox driver does not support duplex channels for this lease.

What it means

Thrown by the plugin-backed sandbox environment driver's openDuplexChannel when the lease was not created by a plugin sandbox provider or the server has no plugin worker manager. Duplex channels (bidirectional command streaming into a sandbox) are only implemented as a host-owned route on a plugin worker; the guard at server/src/services/environment-runtime.ts:2481 requires lease.metadata.sandboxProviderPlugin to be set and a pluginWorkerManager to exist, otherwise the operation is unsupported for that lease.

Source

Thrown at server/src/services/environment-runtime.ts:2481

      }
      return true;
    },

    async syncIn(input) {
      return await callPluginEnvironmentSync("environmentSyncIn", input);
    },

    async syncOut(input) {
      return await callPluginEnvironmentSync("environmentSyncOut", input);
    },

    async openDuplexChannel(input) {
      // Plugin-backed sandbox providers only: open the host-owned duplex route on
      // the plugin worker. The lease scope mirrors the sandbox execute path — the
      // provider driver key, the company, the environment, and the provider lease
      // id — so the route binds to the same worker session the runner streams.
      if (!input.lease.metadata?.sandboxProviderPlugin || !pluginWorkerManager) {
        throw new Error("Sandbox driver does not support duplex channels for this lease.");
      }
      const pluginId = readString(input.lease.metadata?.pluginId);
      const providerKey = readString(input.lease.metadata?.provider);
      const providerLeaseId = readString(input.lease.providerLeaseId);
      if (!pluginId || !providerKey || !providerLeaseId) {
        throw new Error(
          "Sandbox duplex channel needs a plugin id, a provider key, and a provider lease id on the lease.",
        );
      }
      const worker = pluginWorkerManager.getWorker(pluginId);
      if (!worker) {
        throw new Error(`Plugin worker "${pluginId}" is not running for the duplex channel.`);
      }
      const managerInput: WorkerManagerDuplexChannelOpenInput = {
        driverKey: providerKey,
        companyId: input.lease.companyId,
        environmentId: input.environment.id,
        providerLeaseId,

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Verify the lease is a plugin-provider sandbox lease: its metadata must include sandboxProviderPlugin (set at provisioning time by the plugin sandbox driver).
  2. Ensure the server runtime was initialized with a pluginWorkerManager and the sandbox plugin is enabled in server config.
  3. Provision the environment through the plugin sandbox provider so leases carry the required metadata before requesting duplex channels.
  4. If you only need one-shot command execution, use the regular sandbox execute path which does not require a duplex channel.

Example fix

// before
const channel = await runtime.openDuplexChannel({ lease, environment, command }); // throws: driver does not support duplex channels

// after
if (!lease.metadata?.sandboxProviderPlugin) {
  const result = await runtime.execute({ lease, environment, command }); // one-shot path
} else {
  const channel = await runtime.openDuplexChannel({ lease, environment, command });
}
Defensive patterns

Strategy: type-guard

Validate before calling

const isPluginLease = Boolean(lease.metadata?.sandboxProviderPlugin);
const pluginWorkersEnabled = Boolean(serverFeatures.pluginWorkerManager);
if (!isPluginLease || !pluginWorkersEnabled) { await runtime.execute({ lease, environment, command }); } // one-shot fallback path

Type guard

function supportsPluginDuplexChannel(lease: { metadata?: Record<string, unknown> | null }): boolean {
  return lease.metadata?.sandboxProviderPlugin === true || typeof lease.metadata?.sandboxProviderPlugin === "string";
}

Try / catch

try { return await driver.openDuplexChannel(input); } catch (err) { if (/does not support duplex channels/.test(String((err as Error).message))) { return await runtime.execute(input); } throw err; }

Prevention

When it happens

Trigger: Calling openDuplexChannel on the environment runtime with a lease whose metadata lacks sandboxProviderPlugin (a local/docker/inline lease routed to the plugin adapter), or when the server was constructed without a pluginWorkerManager (plugin subsystem disabled) even though the lease metadata claims a plugin provider.

Common situations: Agent tooling attempts to stream commands into a sandbox that was provisioned by a non-plugin driver; the feature flag/config enabling plugin workers is off in that deployment; the lease was created before the plugin sandbox provider existed (old metadata shape).

Related errors


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-21). Data as JSON: /api/errors/76cd561cc94f654d. Report an issue: GitHub.