{"record":{"id":"ec727a874bad4398","repo":"paperclipai/paperclip","slug":"duplex-channel-capability-denied","errorCode":"DUPLEX_CHANNEL_CAPABILITY_DENIED","errorMessage":"Sandbox lease does not grant the duplex command stream capability.","messagePattern":"Sandbox lease does not grant the duplex command stream capability\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/environment-runtime.ts","lineNumber":3485,"sourceCode":"    },\n\n    async openDuplexChannel(\n      input: EnvironmentDriverOpenDuplexChannelInput,\n    ): Promise<CommandManagedDuplexChannel> {\n      const driver = requireDriverKey(getLeaseDriverKey(input.lease, input.environment));\n      if (!driver.openDuplexChannel) {\n        throw new Error(`Environment driver \"${driver.driver}\" does not support duplex channels.`);\n      }\n      // Centralize the duplex channel authorization here. Resolve the exact lease\n      // capability snapshot and refuse unless the effective snapshot grants the\n      // opt-in `duplexCommandStream` capability. This gate runs before the driver\n      // call, so an unauthorized lease never reaches the worker. The\n      // execution-target member gate stays as defense in depth. A driver that\n      // cannot resolve the snapshot fails closed with the fixed refusal.\n      const effective =\n        (await driver.effectiveSandboxCapabilities?.(input)) ?? null;\n      if (effective?.duplexCommandStream !== true) {\n        throw new Error(DUPLEX_CHANNEL_CAPABILITY_DENIED);\n      }\n      return await driver.openDuplexChannel(input);\n    },\n  };\n}\n\nexport type EnvironmentRuntimeService = ReturnType<typeof environmentRuntimeService>;\n","sourceCodeStart":3467,"sourceCodeEnd":3493,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/services/environment-runtime.ts#L3467-L3493","documentation":"Authorization refusal for duplex channels, centralized in the runtime facade: before delegating to the driver it resolves the lease's effective sandbox capability snapshot via driver.effectiveSandboxCapabilities and requires the opt-in duplexCommandStream capability to be exactly true (server/src/services/environment-runtime.ts:3485, constant DUPLEX_CHANNEL_CAPABILITY_DENIED). A missing snapshot, a snapshot without the capability, or a driver that cannot resolve capabilities all fail closed — unauthorized leases never reach the worker.","triggerScenarios":"openDuplexChannel on a lease whose effective capability snapshot does not include duplexCommandStream: true — capability never opted in at lease/environment creation, revoked since acquisition, or the driver cannot resolve a snapshot (returns undefined → null → denied). Reached only after the driver-support check passed.","commonSituations":"New deployments enabling duplex-based tooling without opting leases into the capability; capability gates rolled out server-side before configurations were updated; tests using bare leases without capability metadata.","solutions":["Grant the duplexCommandStream capability in the environment/sandbox configuration the lease is derived from, then acquire a new lease.","Verify with the driver's effectiveSandboxCapabilities (or equivalent API) that the resolved snapshot shows duplexCommandStream === true before opening the channel.","If the snapshot unexpectedly resolves to null, fix the capability resolution path on the driver — absence is treated as denial by design.","Callers that do not need interactive streaming should use execute instead of requesting the capability."],"exampleFix":"// before\nawait envRuntime.openDuplexChannel({ lease, environment, command }); // DUPLEX_CHANNEL_CAPABILITY_DENIED\n\n// after (opt in at environment config / lease acquisition)\nconst lease = await acquireSandboxLease(environment, {\n  capabilities: { duplexCommandStream: true },\n});\nawait envRuntime.openDuplexChannel({ lease, environment, command });","handlingStrategy":"validation","validationCode":"const effective = (await driver.effectiveSandboxCapabilities?.({ lease, environment, command })) ?? null;\nif (effective?.duplexCommandStream !== true) throw new Error(\"Lease lacks duplexCommandStream; opt the environment/lease in before opening a channel.\");","typeGuard":"function leaseGrantsDuplex(snapshot: { duplexCommandStream?: unknown } | null | undefined): boolean {\n  return snapshot?.duplexCommandStream === true;\n}","tryCatchPattern":"try { return await runtime.openDuplexChannel(input); } catch (err) { if ((err as Error).message === \"Sandbox lease does not grant the duplex command stream capability.\") { throw new PermissionError(\"Opt the lease into duplexCommandStream and re-acquire it.\"); } throw err; }","preventionTips":["Opt leases into duplexCommandStream explicitly at acquisition; absence is denial by design.","Do not request the capability broadly — grant it only to leases that need interactive streaming.","Re-check the effective snapshot after capability config changes; leases do not gain capabilities retroactively."],"tags":["sandbox","duplex-channel","authorization","capability","permission-denied"],"backgroundTag":"capability-not-granted","analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-21T17:58:32.592Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}