Worker deploys fine via Wrangler and Web UI but fails via API with SyntaxError

Hi everyone. I'm having a rather odd issue. I'm trying to deploy a worker (I'm using Workers for Platforms but it shouldn't matter) and while it's able to deploy perfectly fine using Wrangler and Web UI, when I deploy via the API, I'm getting a syntax error. Uncaught SyntaxError: Unexpected token 'export' It seems the API will not accept ES module syntax for some reason? Reproduces even with Cloudflare's Hello World example:
export default {
async fetch(request, env, ctx) {
return new Response("Hello World!");
},
};
export default {
async fetch(request, env, ctx) {
return new Response("Hello World!");
},
};
My API code:
// Create form data for Cloudflare API
const formData = new FormData()

// Add metadata
const metadata = {
compatibility_date: "2023-08-23",
main_module: "worker.js",
}
formData.append("metadata", JSON.stringify(metadata))

// Add worker code
formData.append("worker.js", new Blob([workerCode], { type: "application/javascript" }))

// Deploy to Cloudflare Workers
const scriptName = `${userId}-${userWorkerId}`
const cfApiUrl = `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/workers/dispatch/namespaces/${CLOUDFLARE_DISPATCH_NAMESPACE}/scripts/${scriptName}`

console.log(`Deploying worker to Cloudflare API: PUT ${cfApiUrl}`)

const response = await fetch(cfApiUrl, {
method: "PUT",
headers: {
Authorization: `Bearer ${CLOUDFLARE_API_TOKEN}`,
// FormData sets Content-Type automatically
},
body: formData,
})
// Create form data for Cloudflare API
const formData = new FormData()

// Add metadata
const metadata = {
compatibility_date: "2023-08-23",
main_module: "worker.js",
}
formData.append("metadata", JSON.stringify(metadata))

// Add worker code
formData.append("worker.js", new Blob([workerCode], { type: "application/javascript" }))

// Deploy to Cloudflare Workers
const scriptName = `${userId}-${userWorkerId}`
const cfApiUrl = `https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/workers/dispatch/namespaces/${CLOUDFLARE_DISPATCH_NAMESPACE}/scripts/${scriptName}`

console.log(`Deploying worker to Cloudflare API: PUT ${cfApiUrl}`)

const response = await fetch(cfApiUrl, {
method: "PUT",
headers: {
Authorization: `Bearer ${CLOUDFLARE_API_TOKEN}`,
// FormData sets Content-Type automatically
},
body: formData,
})
The multipart stuff is 100% correct and the worker uploads since the error i'm getting shows the exact location of the word export in the code, so the issue is at the deployment stage inside Cloudflare's API Any tips to fix it would be much appreciated! Thanks!
3 Replies
Walshy
Walshy2w ago
content-type should be application/javascript+module If you update the content-type this should work but let me know if it doesn't
import { readFileSync } from "fs";

const workerCode = readFileSync('worker.js');

// Create form data for Cloudflare API
const formData = new FormData()

// Add metadata
const metadata = {
compatibility_date: "2023-08-23",
main_module: "worker.js",
}
formData.append("metadata", JSON.stringify(metadata))

// Add worker code
formData.append("worker.js", new File([workerCode], "worker.js", { type: "application/javascript+module" }))

// Deploy to Cloudflare Workers
const scriptName = `test-worker`
const cfApiUrl = `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_ACCOUNT_ID}/workers/dispatch/namespaces/${process.env.CLOUDFLARE_DISPATCH_NAMESPACE}/scripts/${scriptName}`

console.log(`Deploying worker to Cloudflare API: PUT ${cfApiUrl}`)

const response = await fetch(cfApiUrl, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`,
// FormData sets Content-Type automatically
},
body: formData,
})

console.log(response.status, await response.text())
import { readFileSync } from "fs";

const workerCode = readFileSync('worker.js');

// Create form data for Cloudflare API
const formData = new FormData()

// Add metadata
const metadata = {
compatibility_date: "2023-08-23",
main_module: "worker.js",
}
formData.append("metadata", JSON.stringify(metadata))

// Add worker code
formData.append("worker.js", new File([workerCode], "worker.js", { type: "application/javascript+module" }))

// Deploy to Cloudflare Workers
const scriptName = `test-worker`
const cfApiUrl = `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_ACCOUNT_ID}/workers/dispatch/namespaces/${process.env.CLOUDFLARE_DISPATCH_NAMESPACE}/scripts/${scriptName}`

console.log(`Deploying worker to Cloudflare API: PUT ${cfApiUrl}`)

const response = await fetch(cfApiUrl, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`,
// FormData sets Content-Type automatically
},
body: formData,
})

console.log(response.status, await response.text())
This code works - changes: * application/javascript -> application/javascript+module * Changed Blob to File and added the filename worker.js - this is needed for the main part to be recognised Sorry for the confusion here - we'll improve the docs around this
max
maxOP2w ago
Deployed succesfuly Thanks! 🙌🏻 Yeah I don't think i've seen this in the docs Halfway through debugging I had a hope that maybe cloudflare Node package would help but that isn't super documented either 😄 Either way, thanks for the help 🙏🏻
Walshy
Walshy2w ago
yeah our docs are lacking on the actual content upload part which can be the most confusing at times - we'll fix that asap!

Did you find this page helpful?