Mount buckets·续
// Read-only local mount
await sandbox.mountBucket("MY_BUCKET", "/data", {
localBucket: true,
readOnly: true,
});
// Mount a subdirectory
await sandbox.mountBucket("MY_BUCKET", "/images", {
localBucket: true,
prefix: "/uploads/images/",
});
// Read-only local mount
await sandbox.mountBucket('MY_BUCKET', '/data', {
localBucket: true,
readOnly: true
});
// Mount a subdirectory
await sandbox.mountBucket('MY_BUCKET', '/images', {
localBucket: true,
prefix: '/uploads/images/'
});
Local development considerations
During local development, files are synchronized between R2 and the container using a periodic sync process rather than a direct filesystem mount. Keep the following in mind:
- Synchronization window - A brief delay exists between when a file is written and when it appears on the other side. For example, if you upload a file to R2 and then immediately read it from the mounted path in the container, the file may not yet be available. Allow a short window for synchronization to complete before reading recently written data.
- High-frequency writes - Rapid successive writes to the same file path may take slightly longer to fully propagate. For best results, avoid writing to the same file from both R2 and the container at the same time.
- Bidirectional sync - Changes made in the container are synced to R2, and changes made in R2 are synced to the container. Both directions follow the same periodic sync model.
Note
These considerations apply to local development with wrangler dev only. In production, bucket mounts use a direct filesystem mount with no synchronization delay. Local sync-style behavior may not fully reflect how a production mount overlays the target path.
Unmount buckets
// Mount for processing
await sandbox.mountBucket("MY_BUCKET", "/data");
// Do work
await sandbox.exec("python process_data.py");
// Clean up
await sandbox.unmountBucket("/data");
// Mount for processing
await sandbox.mountBucket('MY_BUCKET', '/data');
// Do work
await sandbox.exec('python process_data.py');
// Clean up
await sandbox.unmountBucket('/data');
Automatic cleanup
Mounted buckets are automatically unmounted when the sandbox is destroyed. Manual unmounting is optional.
Other providers
The SDK supports any S3-compatible object storage. Here are examples for common providers:
Amazon S3
await sandbox.mountBucket("my-s3-bucket", "/data", {
endpoint: "https://s3.us-west-2.amazonaws.com",
credentials: {
accessKeyId: env.AWS_ACCESS_KEY_ID,
secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
},
});
await sandbox.mountBucket('my-s3-bucket', '/data', {
endpoint: 'https://s3.us-west-2.amazonaws.com',
credentials: {
accessKeyId: env.AWS_ACCESS_KEY_ID,
secretAccessKey: env.AWS_SECRET_ACCESS_KEY
}
});
Google Cloud Storage
await sandbox.mountBucket("my-gcs-bucket", "/data", {
endpoint: "https://storage.googleapis.com",
credentials: {
accessKeyId: env.GCS_ACCESS_KEY_ID,
secretAccessKey: env.GCS_SECRET_ACCESS_KEY,
},
});
await sandbox.mountBucket('my-gcs-bucket', '/data', {
endpoint: 'https://storage.googleapis.com',
credentials: {
accessKeyId: env.GCS_ACCESS_KEY_ID,
secretAccessKey: env.GCS_SECRET_ACCESS_KEY
}
});
GCS requires HMAC keys
Generate HMAC keys in GCS console under Settings > Interoperability.
Other S3-compatible providers
For providers like Backblaze B2, MinIO, Wasabi, or others, use the standard mount pattern:
await sandbox.mountBucket("my-bucket", "/data", {
endpoint: "https://s3.us-west-000.backblazeb2.com",
credentials: {
accessKeyId: env.ACCESS_KEY_ID,
secretAccessKey: env.SECRET_ACCESS_KEY,
},
});
await sandbox.mountBucket('my-bucket', '/data', {
endpoint: 'https://s3.us-west-000.backblazeb2.com',
credentials: {
accessKeyId: env.ACCESS_KEY_ID,
secretAccessKey: env.SECRET_ACCESS_KEY
}
});
For provider-specific configuration, see the s3fs-fuse wiki ↗︎ for supported providers and recommended flags.
Troubleshooting
R2 binding not found error
Error: R2 binding "MY_BUCKET" not found in Worker env
Solution: Ensure your Worker has an r2_buckets binding and that mountBucket() uses the binding name, not the bucket's dashboard name:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"r2_buckets": [
{
"binding": "MY_BUCKET",
"bucket_name": "my-r2-bucket"
}
]
}
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-r2-bucket"
Credential-less R2 mount fails immediately
Solution: Ensure your Worker entrypoint exports ContainerProxy. If you are using an older Wrangler version, you may also need the enable_ctx_exports compatibility flag.
Missing credentials error
Error: MissingCredentialsError: No credentials found
Solution: This error only applies when you mount a remote S3-compatible endpoint by setting endpoint. Set credentials as Worker secrets:
npx wrangler secret put R2_ACCESS_KEY_ID
npx wrangler secret put R2_SECRET_ACCESS_KEY
or
npx wrangler secret put AWS_ACCESS_KEY_ID
npx wrangler secret put AWS_SECRET_ACCESS_KEY
Mount failed error
Error: S3FSMountError: mount failed
Common causes:
- Incorrect endpoint URL
- Invalid credentials
- Missing
ContainerProxyexport, or on older Wrangler versions missingenable_ctx_exports - Bucket does not exist
- Network connectivity issues
Verify your binding or endpoint configuration:
try {
await sandbox.mountBucket("MY_BUCKET", "/data");
} catch (error) {
console.error("Mount failed:", error.message);
// Check binding name, ContainerProxy export, or remote endpoint configuration
}
try {
await sandbox.mountBucket('MY_BUCKET', '/data');
} catch (error) {
console.error('Mount failed:', error.message);
// Check binding name, ContainerProxy export, or remote endpoint configuration
}
Path already mounted error
Error: InvalidMountConfigError: Mount path already in use
Solution: Unmount first or use a different path:
// Unmount existing
await sandbox.unmountBucket("/data");
// Or use different path
await sandbox.mountBucket("bucket2", "/storage", { endpoint: "..." });
// Unmount existing
await sandbox.unmountBucket('/data');
// Or use different path
await sandbox.mountBucket('bucket2', '/storage', { endpoint: '...' });
Slow file access
File operations on mounted buckets are slower than local filesystem due to network latency.
Solution: Copy frequently accessed files locally:
// Copy to local filesystem
await sandbox.exec("cp", {
args: ["/data/large-dataset.csv", "/workspace/dataset.csv"],
});
// Work with local copy (faster)
await sandbox.exec("python", {
args: ["process.py", "/workspace/dataset.csv"],
});
// Save results back to bucket
await sandbox.exec("cp", {
args: ["/workspace/results.json", "/data/results/output.json"],
});
// Copy to local filesystem
await sandbox.exec('cp', { args: ['/data/large-dataset.csv', '/workspace/dataset.csv'] });
// Work with local copy (faster)
await sandbox.exec('python', { args: ['process.py', '/workspace/dataset.csv'] });
// Save results back to bucket
await sandbox.exec('cp', { args: ['/workspace/results.json', '/data/results/output.json'] });
Best practices
- Mount early - Mount buckets at sandbox initialization
- Choose the right mount mode - Use R2 binding mounts when you want Worker-managed R2 access, or use
endpointfor explicit R2, S3, GCS, and other S3-compatible providers - Secure credentials - Always use Worker secrets, never hardcode
- Read-only when possible - Protect data with read-only mounts
- Mount the narrowest path - Use prefixes to expose only the data a sandbox needs
- Mount paths - Prefer
/data,/storage, or/mnt/*; if you mount under/workspace, account for the mount overlaying that path in production - Handle errors - Wrap mount operations in
try...catchblocks - Optimize access - Copy frequently accessed files locally
Related resources
- Persistent storage tutorial - Complete R2 example
- Backup and restore - Persist a project directory such as
/workspace - Storage API reference - Full method documentation
- Environment variables - Credential configuration for remote endpoint mounts
- Wrangler configuration - Configure R2 bindings and compatibility flags
- R2 documentation - Learn about Cloudflare R2
- Outbound traffic - Learn how
ContainerProxyand outbound interception work
Was this helpful?
YesNo
On this page
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/sandbox/sdk/guides/mount-buckets/#page","headline":"Mount buckets","description":"Mount S3-compatible object storage as local filesystems with the Sandbox SDK 0.x.","url":"https://developers.cloudflare.com/sandbox/sdk/guides/mount-buckets/","inLanguage":"en","image":"https://developers.cloudflare.com/sandbox/sdk/guides/mount-buckets/og.png?v=546520f95679accb","dateModified":"2026-09-30","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
description: Intercept and handle outbound HTTP from Sandbox SDK 0.x sandboxes using Workers. title: Handle outbound traffic image: https://developers.cloudflare.com/sandbox/sdk/guides/outbound-traffic/og.png?v=125fa5b5302dfaf0
Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/sandbox/llms.txt
Use this file to discover all available pages before exploring further.
Docs