windmill-labs/windmill · error · Error

You can't use this function in a standalone script or flow s

Error message

You can't use this function in a standalone script or flow step preview. Please use it in a flow or a flow preview.

What it means

slackApproval (Slack approval helper) requires the flow job id environment variable (WM_FLOW_JOB_ID), which Windmill only injects when code runs inside a flow (or a flow preview). In a standalone script or flow-step preview the variable is absent, so the client throws to prevent an approval that could never resolve.

Source

Thrown at typescript-client/client.ts:1354

 * ```
 *
 * **Note:** This function requires execution within a Windmill flow or flow preview.
 */
export async function requestInteractiveSlackApproval({
  slackResourcePath,
  channelId,
  message,
  approver,
  defaultArgsJson,
  dynamicEnumsJson,
  resumeButtonText,
  cancelButtonText,
}: SlackApprovalOptions): Promise<void> {
  const workspace = getWorkspace();
  const flowJobId = getEnv("WM_FLOW_JOB_ID");

  if (!flowJobId) {
    throw new Error(
      "You can't use this function in a standalone script or flow step preview. Please use it in a flow or a flow preview."
    );
  }

  const flowStepId = getEnv("WM_FLOW_STEP_ID");
  if (!flowStepId) {
    throw new Error("This function can only be called as a flow step");
  }

  // Only include non-empty parameters
  const params: {
    approver?: string;
    message?: string;
    slackResourcePath: string;
    channelId: string;
    flowStepId: string;
    defaultArgsJson?: string;
    dynamicEnumsJson?: string;

View on GitHub (pinned to e474e8803c)

Solutions

  1. Run the code as part of a full flow execution, not a standalone script or step preview
  2. Use the flow preview mode that sets flow context (flow preview, not step preview)
  3. Guard the call with a check for WM_FLOW_STEP_ID / WM_FLOW_JOB_ID and provide an alternative path for tests
  4. Mock getEnv in unit tests for the approval logic

Example fix

// before (inside a standalone script)
await slackApproval({ channel: 'C123', text: 'Deploy?' })
// after — only call within a flow, or guard it
if (getEnv('WM_FLOW_JOB_ID')) {
  await slackApproval({ channel: 'C123', text: 'Deploy?' })
} else {
  console.log('skipping approval outside flow context')
}
Defensive patterns

Strategy: validation

Validate before calling

if (!getEnv('WM_FLOW_JOB_ID')) {
  throw new Error('slackApproval requires a flow context; run inside a flow, not a standalone script or step preview')
}

Type guard

function inFlowContext(): boolean {
  return !!getEnv('WM_FLOW_JOB_ID')
}

Try / catch

try {
  await slackApproval(opts)
} catch (e) {
  if (e.message.includes('standalone script or flow step preview')) {
    console.error('Call slackApproval only from a real flow run')
  } else throw e
}

Prevention

When it happens

Trigger: Calling slackApproval(...) from a standalone script run or from a flow step preview where WM_FLOW_JOB_ID is not set.

Common situations: Testing approval code with 'run this step only' (preview) instead of a full flow run; moving a flow step's code into a standalone script and forgetting the function is flow-only.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/f7b1e260a3600785. Report an issue: GitHub.