{"record":{"id":"708d678da1914247","repo":"pulumi/pulumi","slug":"pre-step-event-returned-an-error-w","errorCode":null,"errorMessage":"pre-step event returned an error: %w","messagePattern":"pre-step event returned an error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resource/deploy/step_executor.go","lineNumber":489,"sourceCode":"// verbatim to the post-step event.\n//\n\n// executeStep executes a single step, returning true if the step execution was successful and\n// false if it was not.\nfunc (se *stepExecutor) executeStep(workerID int, step Step) error {\n\tvar payload any\n\tevents := se.deployment.events\n\n\t// DiffSteps are special, we just use them for step worker parallelism but they shouldn't be passed to the rest of\n\t// the system.\n\t_, isDiff := step.(*DiffStep)\n\n\tif events != nil && !isDiff {\n\t\tvar err error\n\t\tpayload, err = events.OnResourceStepPre(step)\n\t\tif err != nil {\n\t\t\tse.log(workerID, \"step %v on %v failed pre-resource step: %v\", step.Op(), step.URN(), err)\n\t\t\treturn fmt.Errorf(\"pre-step event returned an error: %w\", err)\n\t\t}\n\t}\n\n\treturn se.continueExecuteStep(payload, workerID, step)\n}\n\nfunc (se *stepExecutor) continueExecuteStep(payload any, workerID int, step Step) error {\n\tevents := se.deployment.events\n\n\tse.log(workerID, \"applying step %v on %v (preview %v)\", step.Op(), step.URN(), se.deployment.opts.DryRun)\n\tstatus, stepComplete, err := step.Apply()\n\n\t// DiffSteps are special, we just use them for step worker parallelism but they shouldn't be passed to the rest of\n\t// the system.\n\tif _, isDiff := step.(*DiffStep); isDiff {\n\t\treturn nil\n\t}\n","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/pkg/resource/deploy/step_executor.go#L471-L507","documentation":"Before executing a resource step, the engine emits a pre-step event to subscribers via events.OnResourceStepPre. If that handler returns an error, the step is not executed and the engine wraps the failure as 'pre-step event returned an error'. Like other event errors, it reflects a problem in an event consumer, not in the resource operation itself.","triggerScenarios":"An event subscriber's OnResourceStepPre fails — e.g. the display/backend event channel is broken, a policy/preevent callback errors, or the Automation API consumer throws while handling the step-pre event.","commonSituations":"Pulumi Cloud event publishing outage; policy pack or crossguard callback crash; automation program crashing mid-deploy while the engine is still running; serializing an unserializable payload in a custom event consumer.","solutions":["Look at the logged line 'failed pre-resource step: %v' for the underlying handler error.","Fix or remove the failing event subscriber (policy pack, automation consumer) before retrying.","Check backend connectivity (PULUMI_ACCESS_TOKEN, self-hosted endpoint) if events publish to Pulumi Cloud.","Retry the deployment once the consumer is fixed; the affected resource step never ran, so re-run is required."],"exampleFix":"// before: automation API throws inside onEvent and aborts the deploy\nawait stack.up({ onEvent: ev => { if (ev.someField) throw new Error('bad'); } });\n// after: log instead of throwing inside the event handler\nawait stack.up({ onEvent: ev => { if (ev.someField) console.error('bad event', ev); } });","handlingStrategy":"try-catch","validationCode":"// smoke-test policy packs before wiring them into deploys\n// pulumi policy rm <org>/<name> && pulumi policy publish <dir> && pulumi policy enable <org>/<name>","typeGuard":null,"tryCatchPattern":"try {\n  await stack.up({ onEvent: handle });\n} catch (e) {\n  if (/pre-step event returned an error/.test(String(e))) {\n    console.error('A pre-step event handler (policy/backend/automation) failed; inspect 'failed pre-resource step' log line');\n  }\n  throw e;\n}","preventionTips":["Test policy packs locally with `pulumi policy new` + preview before enabling org-wide.","Wrap all onEvent consumer logic in try/catch that logs instead of throwing.","Check backend event publishing health (network, token) before large deploys.","Keep Automation API consumers alive for the full stack operation."],"tags":["engine","events","deploy","policy"],"backgroundTag":"event-consumer-failed","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}