How to trigger an activity during external cancellation

Hello!

I have a workflow that sometimes can be cancelled externally from the Temporal UI using the Request Cancel button and I’m unable to do it without receiving a Temporal error

I copied the same lines of code that we have in the TypeScript SDK tutorial here: Interrupt a Workflow - TypeScript SDK | Temporal Platform Documentation

It works to detect an external cancel, but doesn’t works when I try to execute an activity during cancelation.

Example:

import * as wf from "@temporalio/workflow";
import { CancellationScope, isCancellation, proxyActivities } from "@temporalio/workflow";

import type { actionActivities } from "@temporal/activities";

const {
  recordAction,
  completeAction,
  rejectAction,
  cancelAction,
  expireAction
} = proxyActivities<typeof actionActivities>({
  taskQueue: "action",
  startToCloseTimeout: "10 seconds",
});

export async function myActionWorkflow(workflowId: string, args: ActionWorkflowArgs) {
  // Example code
  await recordAction(args);

  // This one works perfect
  wf.setHandler(cancelSignal, async (input: CancelArgs) => {
    await cancelAction(args, input);
  });
  
  wf.setHandler(rejectSignal, async (input: RejectArgs) => {
    await rejectAction(args, input);
  });

  try {
    const timer = createTimer(86000);
    const timerExpiredPromise = timer.then(async () => {
      await expireAction(args);
    });

    // Just an example to don't show unnecessary code
    await wf.sleep("3 day");
  } catch (error) {
    if (isCancellation(error)) {
      wf.log.info("Workflow cancelled externally"); // I see this log

      await CancellationScope.nonCancellable(() =>
        cancelAction(args, {}),
      );

      wf.log.info("Cleanup: cancelAction completed"); // I don't see this log
    }
  }
}

The code in cancelAction is just a SQL insert in Drizzle.

export const cancelAction = async (...) => {
  const [inserted] = await db
    .insert(traces)
    .values({
      id: uuid(),
      actionId: actionId,
      status: "CANCEL"
    })
    .returning();

  if (!inserted) {
    throw new Error("Failed to create trace");
  }

  return { traceId: inserted.id };
} 

The error that I’m seeing is the following:

2025-12-23T19:59:05.306Z [INFO] Workflow cancelled externally - {
  sdkComponent: 'workflow',
  taskQueue: '...',
  namespace: '...',
  workflowId: 'my-workflow-name-workflow_id',
  runId: '...uuid...',
  workflowType: 'myWorkflowName'
}

2025-12-23T19:59:05.306407Z  WARN temporal_sdk_core::worker::workflow: Failing workflow task run_id=...uuid... failure=Failure { failure: Some(Failure { message: "Workflow cancelled", source: "TypeScriptSDK", stack_trace: "CancelledFailure: Workflow cancelled\n    at RootCancellationScope.cancel (/Project/route/node_modules/@temporalio/workflow/src/cancellation-scope.ts:264:16)\n    at Activator.cancelWorkflow (/Project/route/node_modules/@temporalio/workflow/src/internals.ts:481:19)\n    at /Project/route/node_modules/@temporalio/workflow/src/worker-interface.ts:136:29\n    at Object.activate (/Project/route/node_modules/@temporalio/workflow/src/worker-interface.ts:160:2)\n    at evalmachine.<anonymous>:1:18", encoded_attributes: None, cause: None, failure_info: Some(CanceledFailureInfo(CanceledFailureInfo { details: None })) }), force_cause: Unspecified }

The only think that I can think of based on the message is that I can’t trigger an activity if the workflow has been cancelled but as I’m new in Temporal I have no idea.

Just in case I want to use the same activity when I receive a cancel signal and when I execute Request cancel from the UI.

Thanks in advance for your insights!