Error handling seems quite complex. I have a tail worker that should post to the bug tracking app, b

Error handling seems quite complex. I have a tail worker that should post to the bug tracking app, but it doesn't seem to catch exceptions at all tail worker excerpt:
async tail(events, env, ctx) {
// Check if events array exists and has items
if (!Array.isArray(events) || events.length === 0) {
return new Response("No events found", { status: 200 });
}

// Only proceed if there's an exception AND exceptions array is not empty
const event = events[0];
if (event.outcome !== "exception" || !event.exceptions?.length) {
return new Response("No exception found", { status: 200 });
}

// Log the event structure to help us understand the data
console.log("Tail worker event:", JSON.stringify(events, null, 2));

...
async tail(events, env, ctx) {
// Check if events array exists and has items
if (!Array.isArray(events) || events.length === 0) {
return new Response("No events found", { status: 200 });
}

// Only proceed if there's an exception AND exceptions array is not empty
const event = events[0];
if (event.outcome !== "exception" || !event.exceptions?.length) {
return new Response("No exception found", { status: 200 });
}

// Log the event structure to help us understand the data
console.log("Tail worker event:", JSON.stringify(events, null, 2));

...
workflow step
const payload = await step.do('prepares payload', async () => {
const isDev = this.env.ENVIRONMENT === 'dev';
const data = isDev ? mockData : event.payload;

console.log("Received payload:", JSON.stringify(data, null, 2));
throw new Error("Testing error handling with payload data");

return data;
});
const payload = await step.do('prepares payload', async () => {
const isDev = this.env.ENVIRONMENT === 'dev';
const data = isDev ? mockData : event.payload;

console.log("Received payload:", JSON.stringify(data, null, 2));
throw new Error("Testing error handling with payload data");

return data;
});
What am I missing? It never throws the error
19 Replies
Lila Rest
Lila Rest2mo ago
Hey there! Is there any possibility of running some of the steps of a workflow in parallel? For example, in different worker invocations to minimize the overall execution speed?
Matt Silverlock
Matt Silverlock2mo ago
You can always fire off another Workflow, even from within a Workflow. Workflows are the way to run tasks concurrently, or in parallel.
Bonadio
Bonadio2mo ago
Hi, what is the use of the return of the run function in the workflow? I saw in the twillio example that it returns a value. https://github.com/craigsdennis/twilio-cloudflare-workflow/blob/main/src/index.ts
export class NeverGonnaWorkflow extends WorkflowEntrypoint<Env, NeverGonnaParams> {
async run(event: WorkflowEvent<NeverGonnaParams>, step: WorkflowStep) {
const { to, host, content } = event.payload;
await step.sleep('wait for the right moment', '135 seconds');
const callSid = await step.do('call person back', async () => {
const client = new Twilio(this.env.TWILIO_ACCOUNT_SID, this.env.TWILIO_AUTH_TOKEN);
// Say verb here does text to speech
// Play allows you to play media.
// The mp3 file is hosted on Cloudflare Workers using dynamic assets
const twiml = `
<Response>
<Say>Hello from a Cloudflare Workflow!</Say>
<Say>You said "${content}".</Say>
<Say>Check out this classic:</Say>
<Play>https://${host}/classic.mp3</Play>
</Response>`;
const call = await client.calls.create({
to,
from: this.env.TWILIO_PHONE_NUMBER,
twiml,
});
return call.sid;
});

return { success: true, callSid }; // <------ How to use this?

}
}
export class NeverGonnaWorkflow extends WorkflowEntrypoint<Env, NeverGonnaParams> {
async run(event: WorkflowEvent<NeverGonnaParams>, step: WorkflowStep) {
const { to, host, content } = event.payload;
await step.sleep('wait for the right moment', '135 seconds');
const callSid = await step.do('call person back', async () => {
const client = new Twilio(this.env.TWILIO_ACCOUNT_SID, this.env.TWILIO_AUTH_TOKEN);
// Say verb here does text to speech
// Play allows you to play media.
// The mp3 file is hosted on Cloudflare Workers using dynamic assets
const twiml = `
<Response>
<Say>Hello from a Cloudflare Workflow!</Say>
<Say>You said "${content}".</Say>
<Say>Check out this classic:</Say>
<Play>https://${host}/classic.mp3</Play>
</Response>`;
const call = await client.calls.create({
to,
from: this.env.TWILIO_PHONE_NUMBER,
twiml,
});
return call.sid;
});

return { success: true, callSid }; // <------ How to use this?

}
}
GitHub
twilio-cloudflare-workflow/src/index.ts at main · craigsdennis/twil...
Use Cloudflare Workers to create a scheduled durable execution with your Twilio applications - craigsdennis/twilio-cloudflare-workflow
Matt Silverlock
Matt Silverlock2mo ago
You can capture that value when you inspect an instances’ status. This can be useful if your Workflow is computing some kind of result, storing data against a key, or generating some kind of identifier
Lila Rest
Lila Rest2mo ago
Thanks Matt! And will this new workflow run in the same thread or in another? I know that workers called from other workers will run on the same resources. We are executing a huge tree of operations and I’m trying to maximize the speed of execution.
Matt Silverlock
Matt Silverlock2mo ago
That wont affect it here.
Lila Rest
Lila Rest2mo ago
To be 100% sure you're saying that calling a workflow from another will happen in two separate threads?
Matt Silverlock
Matt Silverlock2mo ago
I'm saying it's no different from any other Worker invocation. If the Workflow is a different Workflow (script) then it is likely to spawn a new isolate. We don't make any more guarantees than that.
Unknown User
Unknown User2mo ago
Message Not Public
Sign In & Join Server To View
Matt Silverlock
Workers scripts edit + read:
No description
Lila Rest
Lila Rest5w ago
Ah I see, all clear!
m.muiznieks
m.muiznieks4w ago
Yes, I've noticed the same thing for me as well. Also the response that request is queued comes after 60-80s. The time until START of the step since receiving is 40+ minutes. :)) (thats the reason I came here for looking is this an issue for anyone else). My account ID: 5e3dea7b807381cba36b9292bde14920 Additionally I can say that even sending the requests to my workflow worker gets even 60 to 90 seconds to receive any response from them. Is this a feature? I was not aware of this before.
No description
Aslak Hellesoy
Hi all. Is it possible to pause/resume workflow steps and wait for user input? We're using workflows for order processing. For new users, we require that the user verifies their identity with an external KYC provider. Is there a way to wrap this in a step that will block until the user has verified their identity? Some kind of signal mechanism similar to what Temporal has? Thanks in advance.
m.muiznieks
m.muiznieks4w ago
Also... around 60 instances are marked as queued. But none shows up at any time window. Are there any possibilities to "restart" the workflow?
No description
Chris Jayden
Chris Jayden4w ago
I'm running a workflow to do some R2 work. However, when I'm not running --remote, no real operations are taking place on my buckets. So calling list doesn't return anything. however, when i do run --remote and call my worfklow, i get a workflow.not_found.
Is there something I'm missing?
Hello, I’m Allie!
Afaik, remote mode doesn’t work for Workflows yet
Chris Jayden
Chris Jayden4w ago
Thanks for chiming in. Any other way to test my workflows w/ R2?
Hello, I’m Allie!
You should be able to do lists in local mode, via the CLI, if that is what you mean?
Chris Jayden
Chris Jayden4w ago
I'm trying to query my file in my worker during a workflow. So env.MY_BUCKET.get() or env.MY_BUCKET.list(). But it won't return actual files since I'm developing locally, but i can't set it to --remote because workflows are not supported in remote

Did you find this page helpful?