paperclipai/paperclip · error

Daytona SSH access did not return a token or SSH command.

Error message

Daytona SSH access did not return a token or SSH command.

What it means

Thrown by createSshConnection when Daytona SDK's createSshAccess returns neither a usable token nor a command/sshCommand string. The connection command is derived from access.command, access.sshCommand, or constructed from token; if none yield a non-empty command, the SSH session cannot be established.

Source

Thrown at packages/plugins/sandbox-providers/daytona/src/plugin.ts:622

    throw new Error(
      "Daytona interactive setup requires @daytonaio/sdk Sandbox.createSshAccess support.",
    );
  }

  const fallbackExpiresAt = expiresAtForMinutes(expiresInMinutes);
  const access = await createSshAccess.call(sandbox, expiresInMinutes);
  const token = typeof access.token === "string" && access.token.trim().length > 0
    ? access.token.trim()
    : null;
  const commandFromAccess =
    typeof access.command === "string" && access.command.trim().length > 0
      ? access.command.trim()
      : typeof access.sshCommand === "string" && access.sshCommand.trim().length > 0
        ? access.sshCommand.trim()
        : null;
  const command = commandFromAccess ?? (token ? `ssh ${token}@${DAYTONA_SSH_GATEWAY_HOST}` : null);
  if (!command) {
    throw new Error("Daytona SSH access did not return a token or SSH command.");
  }
  const expiresAt = typeof access.expiresAt === "string" && access.expiresAt.trim().length > 0
    ? access.expiresAt.trim()
    : fallbackExpiresAt;

  return {
    connectionSummary: {
      type: "ssh",
      username: "token",
      hostRedacted: true,
      portRedacted: true,
      commandRedacted: true,
      expiresAt,
      metadata: {
        provider: "daytona",
        expiresInMinutes,
      },
    },

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Upgrade or align @daytonaio/sdk to the version whose createSshAccess returns token/command fields the plugin expects.
  2. Verify the Daytona account has SSH access permissions and the gateway is configured.
  3. Retry the interactive setup in case of a transient incomplete response.
  4. Inspect the access object shape returned by the SDK to detect a renamed field.
Defensive patterns

Strategy: type-guard

Validate before calling

function sshAccessHasUsableResponse(access: { token?: unknown; command?: unknown; sshCommand?: unknown }): boolean {
  const tok = typeof access.token === 'string' && access.token.trim().length > 0;
  const cmd = typeof access.command === 'string' && access.command.trim().length > 0
    || typeof access.sshCommand === 'string' && access.sshCommand.trim().length > 0;
  return tok || cmd;
}

Try / catch

try {
  const session = await createSshConnection(sandbox, expiresInMinutes);
} catch (e) {
  if (e instanceof Error && e.message.includes('did not return a token or SSH command')) {
    // SDK returned no token/command — align SDK version or check permissions
  }
  throw e;
}

Prevention

When it happens

Trigger: createSshAccess.call succeeds but access.token is not a non-empty string AND neither access.command nor access.sshCommand is a non-empty string. The fallback `ssh <token>@<gateway>` also cannot be built without a token.

Common situations: Daytona SDK version returns a different response shape (renamed fields); the SDK returned an empty/null token due to an account/permission issue; transient Daytona API issue returning an incomplete SSH access object; incompatible SDK response contract.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/45d709c7e10ef0f3. Report an issue: GitHub.