When a Sandbox is running, call the append mount operation to add a JuiceFS mount without recreating the Sandbox.
How it works
When a Sandbox is in the running
state, append a JuiceFS mount without recreating the Sandbox. When appending, specify the JuiceFS mount configuration directly, or reference an existing Agent Sandbox volume of the JuiceFS type by name.
To specify the mount configuration when you create a Sandbox, see Mount JuiceFS dynamically.
Prerequisites
-
The Sandbox is in the running state. If the Sandbox is paused, resume it first.
-
The Agent Sandbox API key used in the request belongs to the same team as the target Sandbox.
-
The Sandbox uses a custom template of the second-generation runtime (MicroVM), and the JuiceFS Enterprise Edition client, the RADOS runtime library, and FUSE 2 are installed. For information about the image requirements, see Mount a JuiceFS Volume.
-
The Sandbox is configured with the complete Virtual Private Cloud (VPC) information required to access the JuiceFS service, including
vpcId,securityGroupId, and a non-emptyvSwitchIds. -
If you specify the configuration directly, prepare the JuiceFS file system name, the service endpoint, and a token that can access the destination directory. If you reference an existing volume, Create a JuiceFS Volume in the same team in advance and obtain the name of an available volume.
The append mount operation inherits the current VPC configuration of the Sandbox and does not replace it with the mountConfig.vpcConfig of the new volume. If the required VPC configuration is missing, you must recreate the Sandbox. For information about how to configure the VPC when you create a Sandbox, see Mount JuiceFS dynamically and Mount a JuiceFS Volume.
JuiceFS uses a token to access a file system, so you do not need to configure a Resource Access Management (RAM) role to mount JuiceFS.
API operation and parameters
POST /sandboxes/{sandboxID}/fc-volume-mounts
The request headers must include X-API-Key and Content-Type: application/json. If the call succeeds, the API returns 204 No Content with an empty response body.
The request body supports both a direct configuration and references to existing volumes. A single request can combine both methods:
|
Field |
Type |
Required |
Description |
|
|
Object |
Provide at least one of this field and |
The JuiceFS mount configuration that you specify directly. For the fields, see the following table. |
|
|
Object array |
Provide at least one of this field and |
References existing volumes by name. |
|
|
String |
Required if you reference a volume. |
The name of a volume in the same team. A volume ID is not supported. |
|
|
String |
Required if you reference a volume. |
The local mount directory in the Sandbox. |
The request must contain at least one valid mount point. The mount configuration in an append request is a JSON object, instead of the metadata or JSON string format used when you create a Sandbox. Field names are case-sensitive. The metadata key used at creation is fc.sandbox.storage.juicefs, and the corresponding field in an append request is juiceFS.
JuiceFS mount parameters
The following fields are in inlineVolumeMounts.juiceFS. If you specify the configuration directly, set the fields as described in the following table:
|
Field |
Type |
Required |
Description |
|
|
Object |
Conditionally required |
The environment variables passed only to the JuiceFS mount process. If the JuiceFS service endpoint is not configured for the Sandbox, specify it by using |
|
|
String |
Conditionally required |
The endpoint that the JuiceFS Enterprise Edition client accesses. Existing and new mounts must use the same endpoint. |
|
|
Object array |
Yes |
The JuiceFS mount points in this request. The list contains 1 to 5 mount points. The total number of existing and new JuiceFS mount points cannot exceed 5. |
|
|
String |
Yes |
The JuiceFS file system name. This is not the name or ID of an Agent Sandbox volume. |
|
|
String |
No |
The remote directory in the JuiceFS file system. Specifying this field explicitly is recommended. |
|
|
String |
Yes |
The local mount directory in the Sandbox. The directory must meet the requirements described in Limits. |
|
|
String |
Yes |
The token used to access the JuiceFS file system. |
|
|
String array |
No |
The additional mount parameters passed to the JuiceFS client. Do not specify the platform-managed |
Do not print tokens or the complete request body in logs.
Local mount directory
mountDir and namedVolumeMounts[].path both specify the local mount directory in the Sandbox. The recommended location is a subdirectory of /home, /mnt, /tmp, or /data. For information about the directory limits, see Limits.
Install the SDK
The example uses httpx to call the append mount operation, and then uses the E2B SDK to connect to the existing Sandbox and verify read and write operations.
pip install "e2b==2.31.0" httpx
Environment variables
|
Environment variable |
Purpose |
Source or value |
|
|
The API key used to call the Agent Sandbox API operations. |
Obtain the API key of the destination team in the Agent Sandbox console. |
|
|
The endpoint of the Agent Sandbox E2B API. |
|
|
|
The domain that the SDK uses to access the Sandbox. |
|
|
|
The ID of the Sandbox that receives the append mount request. |
Obtain the value from the response of the Sandbox creation operation or from the Sandbox list. |
|
|
The endpoint of the JuiceFS Enterprise Edition service. |
Obtain the value from the JuiceFS Enterprise Edition service configuration. The endpoint must be reachable within the VPC of the Sandbox. |
|
|
The JuiceFS file system name. |
Obtain the value in the JuiceFS Enterprise Edition console. This is not the name of an Agent Sandbox volume. |
|
|
The token used to access the JuiceFS file system. |
Obtain the token in the JuiceFS Enterprise Edition console. The token must have the permissions to access the destination directory. |
|
|
The remote directory in the JuiceFS file system. |
Specify the directory based on your task. Example: |
The storage-specific environment variables are used when you specify the mount configuration directly. If you reference an existing volume, you do not need to set these variables.
Append mount examples
Set the connection information in your local terminal and replace the placeholders with actual values:
export E2B_API_KEY="<YOUR-E2B-API-KEY>"
export E2B_API_URL="https://api.<REGION>.sandbox.aliyuncs.com"
export E2B_DOMAIN="<REGION>.sandbox.aliyuncs.com"
export SANDBOX_ID="<SANDBOX-ID>"
The following code runs on your local machine and accesses files in the Sandbox through the SDK. The example creates a separate test file with a random identifier, writes data to the file, reads the file for verification, deletes the file, and retains the Sandbox. Use a mount configuration that provides read and write permissions. If the mount allows only read operations, modify the verification code as described in Verify the mount.
Sandbox.connect() updates the timeout of the Sandbox. The example uses timeout=300
to set the post-connection timeout to 300 seconds. Adjust the value based on your task. If the timeout is too short, the read and write verification may end before it completes. If it is too long, the idle Sandbox keeps occupying resources and increases cost. For more information about how to set and adjust the timeout, see Timeouts.
Select one of the following methods, or combine both methods in a single request:
-
Specify the mount configuration directly: provide the JuiceFS mount parameters in
inlineVolumeMounts.juiceFSof the request body. -
Reference an existing volume: reference a volume in the same team by name in
namedVolumeMountsof the request body.
Specify the mount configuration directly
The following example appends the remote directory in the JuiceFS file system to /mnt/juicefs and verifies read and write operations. Make sure that the token and the directory permissions allow read and write operations. If the Sandbox already has a JuiceFS mount, the BASE_URL must be the same as the existing endpoint.
export JUICEFS_BASE_URL="https://<JUICEFS-SERVICE-ADDRESS>"
export JUICEFS_VOLUME_NAME="<JUICEFS-FILE-SYSTEM-NAME>"
export JUICEFS_TOKEN="<JUICEFS-TOKEN>"
export JUICEFS_REMOTE_DIR="/datasets/project-a"
Save the following code as append_juicefs.py. Before you run the code, make sure that mount_dir is not used by an existing mount:
import os
from uuid import uuid4
import httpx
from e2b import Sandbox
def require_env(name: str) -> str:
value = os.environ.get(name, "").strip()
if not value:
raise RuntimeError(f"Missing environment variable: {name}")
return value
def verify_read_write(sandbox: Sandbox, mount_dir: str) -> None:
marker_path = f"{mount_dir}/mount-check-{uuid4().hex}.txt"
expected = f"append mount check {uuid4().hex}\n"
sandbox.files.write(marker_path, expected)
try:
content = sandbox.files.read(marker_path)
if content != expected:
raise RuntimeError(f"File content verification failed: {marker_path}")
finally:
sandbox.files.remove(marker_path)
print(f"Read/write verification passed. Test file deleted: {mount_dir}")
api_key = require_env("E2B_API_KEY")
api_url = require_env("E2B_API_URL").rstrip("/")
domain = require_env("E2B_DOMAIN")
sandbox_id = require_env("SANDBOX_ID")
mount_dir = "/mnt/juicefs"
payload = {
"inlineVolumeMounts": {
"juiceFS": {
"envs": {"BASE_URL": require_env("JUICEFS_BASE_URL")},
"mountPoints": [{
"volumeName": require_env("JUICEFS_VOLUME_NAME"),
"remoteDir": require_env("JUICEFS_REMOTE_DIR"),
"mountDir": mount_dir,
"token": require_env("JUICEFS_TOKEN"),
"args": [],
}],
},
},
}
response = httpx.post(
f"{api_url}/sandboxes/{sandbox_id}/fc-volume-mounts",
headers={"X-API-Key": api_key},
json=payload,
timeout=120.0,
)
if response.status_code != 204:
raise RuntimeError(f"Append mount failed: HTTP {response.status_code}, {response.text}")
sandbox = Sandbox.connect(
sandbox_id,
timeout=300,
api_key=api_key,
api_url=api_url,
domain=domain,
)
verify_read_write(sandbox, mount_dir)
python append_juicefs.py
remoteDir specifies the remote directory in JuiceFS, and mountDir specifies the local directory in the Sandbox. The platform converts remoteDir to the --subdir parameter of the client. For information about how to use remote directories, see Mount JuiceFS dynamically.
Reference an existing volume
If an Agent Sandbox volume already exists, replace the payload definition in the preceding script with the following content before the first run. Keep the rest of the code unchanged. Replace name with the name of a volume in the same team. The volume must allow read and write operations for the verification to pass.
payload = {
"namedVolumeMounts": [{
"name": "juicefs-workspace",
"path": mount_dir,
}],
}
name specifies the name of an Agent Sandbox volume, not the name of a JuiceFS file system. If you combine mount methods, envs.BASE_URL must match the baseURL of the referenced volume and the endpoint of the existing JuiceFS mounts.
The two preceding examples demonstrate one mount method each. Select one of them for each run. You cannot append to the same mount directory twice. If the mount succeeds but the verification fails, run only the connection and verification code again. Do not submit the append request again.
If you combine a direct configuration and a volume reference, put both configurations in the same request body and specify a different local mount directory for each mount point. For the complete procedure and the multi-volume examples for volume references, see Append a volume mount.
Verify the mount
The example connects to the Sandbox and verifies file read and write operations only after the API returns 204. The output "Read/write verification passed. Test file deleted" indicates that the write operation, the content comparison, and the deletion are complete.
If the token or the mount configuration allows only read operations, verify read operations only. Before the first run, replace verify_read_write(sandbox, mount_dir) at the end of the example with the following code. Replace <EXISTING-FILE> with the relative path of a file that already exists in the mount directory.
file_path = f"{mount_dir}/<EXISTING-FILE>"
content = sandbox.files.read(file_path, format="bytes")
print(f"Read succeeded: {file_path}, {len(content)} bytes")
A mount that references a volume can also be queried through the SDK after the connection succeeds:
print(sandbox.get_info().volume_mounts)
In the SDK, the volume_mounts field corresponds to the GET /sandboxes/{sandboxID} response, where the field is named volumeMounts. Mounts that use a direct configuration do not appear in this field and must be verified through file access. The existence of a directory does not mean that data access works.
Behavior notes
Releasing a Sandbox does not delete the data in JuiceFS. Clean up test files and task data separately in the storage service or through the mount directory.
Limits
-
The local mount directory must be a normalized absolute Unix path. It cannot be
/, and it cannot contain leading or trailing spaces,.,.., or repeated path separators. -
The local mount directory cannot be a system directory or a subdirectory of one, such as
/bin,/opt,/var, or/dev, and cannot contain a hidden directory such as.cache. To access data through a hidden directory, mount the storage to a directory that meets the requirements and then create a symbolic link that points to the mount directory. -
Local mount directories cannot be duplicated in the same Sandbox, including mount directories of different storage types.
-
Append mounts support only JuiceFS Enterprise Edition.
-
The operation only adds mounts. It does not unmount or replace existing mounts. To remove an existing mount, release and recreate the Sandbox. Omitting an existing mount does not delete it, and submitting the same mount again returns
400. -
In the same Sandbox, the total number of existing and new JuiceFS mount points cannot exceed 5, and all mount points share one JuiceFS service endpoint.
-
Do not concurrently modify the mounts of the same Sandbox.
FAQ
Why is the request rejected by the API key policy?
If the error message is request is not allowed by API key policy, check whether the API key policy allows the mount method and the storage type of this request. For more information, see Manage API keys. This type of rejection occurs at the API authorization stage. Adjusting the RAM role of the storage does not resolve it.
Why does the system report that the volume cannot be found when I mount by name?
Check the volume name in the request, the team that owns the API key, and the region of the API endpoint. Make sure that you use the name of a volume in the same team instead of a volume ID. For more information, see Append a volume mount.
Why does the system report that the volume is unavailable when I mount by name?
Query the status and the status reason of the volume by using GetVolume. Mount the volume only after you confirm that it is available. If a failure reason exists, resolve it first. For more information, see Append a volume mount.
Why does the append mount report that the Sandbox is not running?
If the error message is sandbox must be running, confirm that the target Sandbox is in the running state. If the Sandbox is paused, resume it first. If the Sandbox is released, recreate it.
Why does the append mount report an incomplete VPC configuration for the Sandbox?
If the error message contains FC Function complete VPC configuration is required, the missing configuration belongs to the current Sandbox. The mountConfig.vpcConfig
of the append request or of a new volume does not supply the missing configuration.
When you recreate the Sandbox, you must provide a complete VPC configuration that includes vpcId, securityGroupId, and a non-empty vSwitchIds. When you create a Sandbox, provide these values by using metadata, or use the VPC configuration that the referenced volume stores.
Why does the append mount report a JuiceFS service endpoint conflict?
Check the inlineVolumeMounts.juiceFS.envs.BASE_URL in this request, the baseURL of the referenced volume, and the endpoint used by the existing JuiceFS mounts of the Sandbox. All JuiceFS mounts must use the same endpoint.
For example, if the error message contains JuiceFS Volume baseUrl conflicts with inline JuiceFS envs.BASE_URL, the endpoint that you specify directly conflicts with the endpoint of the referenced volume. Specify the same endpoint or select the corresponding volume. To connect to a different JuiceFS service, use a different Sandbox.
Why does the append mount report a duplicate mount directory?
If the error message contains duplicate mount path or duplicate mount dir, check whether the local mount directories in this request are duplicated. Also check whether a directory is already used by another mount in the Sandbox. Different storage types cannot share the same local mount directory.
Do not submit existing mounts again. Use an unused directory for the new mount. The append operation cannot overwrite or replace existing mounts.
Why is the mount limit exceeded when I append only one mount point?
The number of mounts is calculated from the existing mounts of the Sandbox and the new mounts in this request. Both directly configured mounts and mounts that reference volumes are counted. Do not check only the number of mounts in this request.
Check the number of mounts for the corresponding storage type as described in Limits of this topic. If the limit is reached, mount the new storage in another Sandbox. Changing the local mount directory does not reduce the number of existing mounts.
If the issue persists, or if the API reports that the service is temporarily unavailable, retain the complete error message and the request ID, and contact technical support.