Hi folks - having some trouble with

Hi folks - having some trouble with throwing errors inside a workflow. First, it seems throwing a NonRetryableError, is retried as many times as specified Second, I can't seem to find out where the throw error messages are being returned in the workflow status. The docs seem to say const wf = await MY_WORKFLOW.get(id) and then await wf.status() should return errors, but they are always empty. here is the code I'm using to reproduce:
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
step.do('Step 1', async () => { return 'Step 1 finished!'; });

step.do('Step 2', {
retries: { limit: 2, delay: '1 second', backoff: 'linear', },
}, async () => {
console.log('Trying Step 2');
throw new NonRetryableError('Step 3 failed. Non-retryable');
});
}
}
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
step.do('Step 1', async () => { return 'Step 1 finished!'; });

step.do('Step 2', {
retries: { limit: 2, delay: '1 second', backoff: 'linear', },
}, async () => {
console.log('Trying Step 2');
throw new NonRetryableError('Step 3 failed. Non-retryable');
});
}
}
This logs "trying step 2" three times
21 Replies
wesbos
wesbosOP2mo ago
this is the data returned from workflow.status() promise. No errors in there
No description
wesbos
wesbosOP2mo ago
"wrangler": "^3.108.1" btw
Matt Silverlock
Matt Silverlock2mo ago
cc @Luís Duarte 🧑🍳 @Diogo Ferreira @wesbos - no await step - ? I think your steps are just getting swallowed
wesbos
wesbosOP2mo ago
oh let me try - I was using the default example but re-made this to distill it down. 1 sec same problem with the await.
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
await step.do('Step 1', async () => { return 'Step 1 finished!'; });

await step.do('Step 2', {
retries: { limit: 2, delay: '1 second', backoff: 'linear', },
}, async () => {
console.log('Trying Step 2');
throw new NonRetryableError('Step 3 failed. Non-retryable');
});
}
}
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
await step.do('Step 1', async () => { return 'Step 1 finished!'; });

await step.do('Step 2', {
retries: { limit: 2, delay: '1 second', backoff: 'linear', },
}, async () => {
console.log('Trying Step 2');
throw new NonRetryableError('Step 3 failed. Non-retryable');
});
}
}
Matt Silverlock
Matt Silverlock2mo ago
Give me 30, need to interview this candidate But looks fine...
wesbos
wesbosOP2mo ago
no rush! Just poking around
Matt Silverlock
Matt Silverlock2mo ago
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';
import { NonRetryableError } from 'cloudflare:workflows';

type Env = {
MY_WORKFLOW: Workflow;
};

export class NonRetryableWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
await step.do('my first step', async () => {
console.log('before the retry');
throw new NonRetryableError('Did it retry?');
});

await step.do('some other step', async () => {
console.log('step 2');
return 'Twonce';
});
}
}

export default {
async fetch(req: Request, env: Env): Promise<Response> {
let instance = await env.MY_WORKFLOW.create();
return Response.json({
id: instance.id,
details: await instance.status(),
});
},
};
import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';
import { NonRetryableError } from 'cloudflare:workflows';

type Env = {
MY_WORKFLOW: Workflow;
};

export class NonRetryableWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
await step.do('my first step', async () => {
console.log('before the retry');
throw new NonRetryableError('Did it retry?');
});

await step.do('some other step', async () => {
console.log('step 2');
return 'Twonce';
});
}
}

export default {
async fetch(req: Request, env: Env): Promise<Response> {
let instance = await env.MY_WORKFLOW.create();
return Response.json({
id: instance.id,
details: await instance.status(),
});
},
};
Matt Silverlock
Matt Silverlock2mo ago
No description
Matt Silverlock
Matt Silverlock2mo ago
Oh, I think we might have a beta bug for local dev here.
Seekerdasbatatas
yeah was trying to repro this
ketan
ketan2mo ago
Yeah - both these things do not work as expected in dev by both I mean (1) NonRetryableError immediately haulting execution and (2) Showing error status
Seekerdasbatatas
I'll fix this in a few moments 🙂
wesbos
wesbosOP2mo ago
sweet thanks!
Matt Silverlock
Matt Silverlock2mo ago
Thanks Luis!
wesbos
wesbosOP2mo ago
Similar q: Are the step outputs available in prod as well? If so why is the output different when local?
Seekerdasbatatas
step outputs are not available in prod atm 😅 - we just make it available in local to make debugging easier, while we find out a better way do it :soontm:
wesbos
wesbosOP2mo ago
gotcha- thank you
Seekerdasbatatas
github's CI isn't cooperating with me 🙂 - but that's the PR that fixes this: https://github.com/cloudflare/workers-sdk/pull/8123 i'll check in again when the prerelease version is up
GitHub
fix: nonretryable error and errored step caching by LuisDuarte1 · P...
Fixes WOR-468 Nonretrable error and errored step caching didn&#39;t match prod behavior Tests TODO (before merge) Tests included Tests not necessary because: Wrangler E2E Tests CI Job ...
Seekerdasbatatas
If you want to try it out, while it's not released: npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/13294041025/npm-package-wrangler-8123
wesbos
wesbosOP2mo ago
thank you - will give it a shot tomorrow
Nathan Scheele
Nathan Scheele2mo ago
I just joined the Discord to ask about this same issue! Glad it's being worked on 🙂 (the NonRetryableError issue, that is)

Did you find this page helpful?