Chapter 04 · Cloudflare Deploy
Subchapter 4.299
references/wrangler/gotchas.mdMarkdown6 KBView on GitHub
Cause: Confusion between binding name (code) and resource ID
Solution: Bindings use binding (code name) and id/database_id/bucket_name (resource ID). Preview bindings need separate IDs: preview_id, preview_database_id
Cause: Non-inheritable keys not redefined per environment Solution: Non-inheritable keys (bindings, vars) must be redefined per environment. Inheritable keys (routes, compatibility_date) can be overridden
Cause: Using local simulation instead of remote execution Solution: Choose appropriate remote mode:
wrangler dev (default): Local simulation, fast, limited accuracywrangler dev --remote: Full remote execution, production-accurate, slowerremote: "minimal" in tests for fast tests with real remote bindingsCause: Using local mode when remote resources needed
Solution: Use remote option:
const worker = await startWorker({
config: "wrangler.jsonc",
remote: true // or "minimal" for faster tests
});Cause: Missing compatibility_date
Solution: Always set compatibility_date:
{ "compatibility_date": "2025-01-01" }Cause: Missing script_name for external DOs
Solution: Always specify script_name for external Durable Objects:
{
"durable_objects": {
"bindings": [
{ "name": "MY_DO", "class_name": "MyDO", "script_name": "my-worker" }
]
}
}For local DOs in same Worker, script_name is optional.
Cause: IDs written back to config on first deploy, but config not reloaded Solution: After first deploy with auto-provisioning, config file is updated with IDs. Commit the updated config. On subsequent deploys, existing resources are reused.
Cause: Secrets set with wrangler secret put only work in deployed Workers
Solution: For local dev, use .dev.vars
Cause: Missing Node.js compatibility flag
Solution: Some bindings (Hyperdrive with pg) require:
{ "compatibility_flags": ["nodejs_compat_v2"] }Cause: Asset path mismatch or incorrect html_handling
Solution:
assets.directory points to correct build outputhtml_handling: "auto-trailing-slash" for SPAsnot_found_handling: "single-page-application" to serve index.html for 404s{
"assets": {
"directory": "./dist",
"html_handling": "auto-trailing-slash",
"not_found_handling": "single-page-application"
}
}Cause: Misunderstanding of Smart Placement Solution: Smart Placement only helps when Worker accesses D1 or Durable Objects. It doesn’t affect KV, R2, or external API latency.
{ "placement": { "mode": "smart" } } // Only beneficial with D1/DOsCause: Using outdated API
Solution: Use stable startWorker instead:
import { startWorker } from "wrangler"; // Not unstable_startWorkerCause: Mock function not returning Response
Solution: Always return Response, use fetch(req) for passthrough:
const worker = await startWorker({
outboundService: (req) => {
if (shouldMock(req)) {
return new Response("mocked");
}
return fetch(req); // Required for non-mocked requests
}
});| Resource/Limit | Value | Notes |
|---|---|---|
| Bindings per Worker | 64 | Total across all types |
| Environments | Unlimited | Named envs in config |
| Config file size | ~1MB | Keep reasonable |
| Workers Assets size | 25 MB | Per deployment |
| Workers Assets files | 20,000 | Max number of files |
| Script size (compressed) | 1 MB | Free, 10 MB paid |
| CPU time | 10-50ms | Free, 50-500ms paid |
| Subrequest limit | 50 | Free, 1000 paid |
wrangler logout
wrangler login
wrangler whoamiwrangler check # Validate configUse wrangler.jsonc with $schema for validation.
--remotewrangler tail # Check logs
wrangler deploy --dry-run # Validate
wrangler whoami # Check account limitsrm -rf .wrangler/state # Clear local state
wrangler dev --remote # Use remote bindings
wrangler dev --persist-to ./local-state # Custom persist location
wrangler dev --inspector-port 9229 # Enable debugging# If tests hang, ensure dispose() is called
worker.dispose() // Always cleanup
# If bindings don't work in tests
const worker = await startWorker({
config: "wrangler.jsonc",
remote: "minimal" // Use remote bindings
});