Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/pulumi/gotchas.md
1# Troubleshooting & Best Practices23## Common Errors45### "No bundler/build step" - Pulumi uploads raw code67**Problem:** Worker fails with "Cannot use import statement outside a module"8**Cause:** Pulumi doesn't bundle Worker code - uploads exactly what you provide9**Solution:** Build Worker BEFORE Pulumi deploy1011```typescript12// WRONG: Pulumi won't bundle this13const worker = new cloudflare.WorkerScript("worker", {14content: fs.readFileSync("./src/index.ts", "utf8"), // Raw TS file15});1617// RIGHT: Build first, then deploy18import * as command from "@pulumi/command";19const build = new command.local.Command("build", {20create: "npm run build",21dir: "./worker",22});23const worker = new cloudflare.WorkerScript("worker", {24content: build.stdout.apply(() => fs.readFileSync("./worker/dist/index.js", "utf8")),25}, {dependsOn: [build]});26```2728### "wrangler.toml not consumed" - Config drift2930**Problem:** Local wrangler dev works, Pulumi deploy fails31**Cause:** Pulumi ignores wrangler.toml - must duplicate config32**Solution:** Generate wrangler.toml from Pulumi or keep synced manually3334```typescript35// Pattern: Export Pulumi config to wrangler.toml36const workerConfig = {37name: "my-worker",38compatibilityDate: "2025-01-01",39compatibilityFlags: ["nodejs_compat"],40};4142new command.local.Command("generate-wrangler", {43create: pulumi.interpolate`cat > wrangler.toml <<EOF44name = "${workerConfig.name}"45compatibility_date = "${workerConfig.compatibilityDate}"46compatibility_flags = ${JSON.stringify(workerConfig.compatibilityFlags)}47EOF`,48});49```5051### "False no-changes detection" - Content SHA unchanged5253**Problem:** Worker code updated, Pulumi says "no changes"54**Cause:** Content hash identical (whitespace/comment-only change)55**Solution:** Add build timestamp or version to force update5657```typescript58const version = Date.now().toString();59const worker = new cloudflare.WorkerScript("worker", {60content: code,61plainTextBindings: [{name: "VERSION", text: version}], // Forces new deployment62});63```6465### "D1 migrations don't run on pulumi up"6667**Problem:** Database schema not applied after D1 database created68**Cause:** Pulumi creates database but doesn't run migrations69**Solution:** Use Command resource with dependsOn7071```typescript72const db = new cloudflare.D1Database("db", {accountId, name: "mydb"});7374// Run migrations after DB created75const migration = new command.local.Command("migrate", {76create: pulumi.interpolate`wrangler d1 execute ${db.name} --file ./schema.sql`,77}, {dependsOn: [db]});7879// Worker depends on migrations80const worker = new cloudflare.WorkerScript("worker", {81d1DatabaseBindings: [{name: "DB", databaseId: db.id}],82}, {dependsOn: [migration]});83```8485### "Missing required property 'accountId'"8687**Problem:** `Error: Missing required property 'accountId'`88**Cause:** Account ID not provided in resource configuration89**Solution:** Add to stack config9091```yaml92# Pulumi.<stack>.yaml93config:94cloudflare:accountId: "abc123..."95```9697### "Binding name mismatch"9899**Problem:** Worker fails with "env.MY_KV is undefined"100**Cause:** Binding name in Pulumi != name in Worker code101**Solution:** Match exactly (case-sensitive)102103```typescript104// Pulumi105kvNamespaceBindings: [{name: "MY_KV", namespaceId: kv.id}]106107// Worker code108export default { async fetch(request, env) { await env.MY_KV.get("key"); }}109```110111### "API token permissions insufficient"112113**Problem:** `Error: authentication error (10000)`114**Cause:** Token lacks required permissions115**Solution:** Grant token permissions: Account.Workers Scripts:Edit, Account.Account Settings:Read116117### "Resource not found after import"118119**Problem:** Imported resource shows as changed on next `pulumi up`120**Cause:** State mismatch between actual resource and Pulumi config121**Solution:** Check property names/types match exactly122123```bash124pulumi import cloudflare:index/workerScript:WorkerScript my-worker <account_id>/<worker_name>125pulumi preview # If shows changes, adjust Pulumi code to match actual resource126```127128### "v6.x Worker versioning confusion"129130**Problem:** Worker deployed but not receiving traffic131**Cause:** v6.x requires Worker + WorkerVersion + WorkersDeployment (3 resources)132**Solution:** Use WorkerScript (auto-versioning) OR full versioning pattern133134```typescript135// SIMPLE: WorkerScript auto-versions (default behavior)136const worker = new cloudflare.WorkerScript("worker", {137accountId, name: "my-worker", content: code,138});139140// ADVANCED: Manual versioning for gradual rollouts (v6.x)141const worker = new cloudflare.Worker("worker", {accountId, name: "my-worker"});142const version = new cloudflare.WorkerVersion("v1", {143accountId, workerId: worker.id, content: code, compatibilityDate: "2025-01-01",144});145const deployment = new cloudflare.WorkersDeployment("prod", {146accountId, workerId: worker.id, versionId: version.id,147});148```149150## Best Practices1511521. **Always set compatibilityDate** - Locks Worker behavior, prevents breaking changes1532. **Build before deploy** - Pulumi doesn't bundle; use Command resource or CI build step1543. **Match binding names** - Case-sensitive, must match between Pulumi and Worker code1554. **Use dependsOn for migrations** - Ensure D1 migrations run before Worker deploys1565. **Version Worker content** - Add VERSION binding to force redeployment on content changes1576. **Store secrets in stack config** - Use `pulumi config set --secret` for API keys158159## Limits160161| Resource | Limit | Notes |162|----------|-------|-------|163| Worker script size | 10 MB | Includes all dependencies, after compression |164| Worker CPU time | 10ms (free), 30s default / 5min max (paid) | Per request |165| KV keys per namespace | Unlimited | 1000 ops/sec write, 100k ops/sec read |166| R2 storage | Unlimited | Class A ops: 1M/mo free, Class B: 10M/mo free |167| D1 databases | 50,000 per account | Free: 10 per account, 5 GB each |168| Queues | 10,000 per account | Free: 1M ops/day |169| Pages projects | 500 per account | Free: 100 projects |170| API requests | Varies by plan | ~1200 req/5min on free |171172## Resources173174- **Pulumi Registry:** https://www.pulumi.com/registry/packages/cloudflare/175- **API Docs:** https://www.pulumi.com/registry/packages/cloudflare/api-docs/176- **GitHub:** https://github.com/pulumi/pulumi-cloudflare177- **Cloudflare Docs:** https://developers.cloudflare.com/178- **Workers Docs:** https://developers.cloudflare.com/workers/179180---181See: [README.md](./README.md), [configuration.md](./configuration.md), [api.md](./api.md), [patterns.md](./patterns.md)182