jackwener/OpenCLI · error · CliError

TAP_MISSING_PARAMS

TAP_MISSING_PARAMS

Error message

tap: store and action are required

What it means

stepTap requires both a store name and an action name in its config, because a tap interacts with a framework store by dispatching a named action. If either is missing after config resolution, it throws CliError with code TAP_MISSING_PARAMS. This is a fail-fast configuration validation so the tap does not silently do nothing.

Source

Thrown at src/pipeline/steps/tap.ts:42

  args?: unknown[];
}

export async function stepTap(
  page: IPage | null,
  params: unknown,
  data: unknown,
  args: Record<string, unknown>,
): Promise<unknown> {
  const cfg: TapParams = typeof params === 'object' && params !== null ? (params as TapParams) : {};
  const storeName = String(render(cfg.store ?? '', { args, data }));
  const actionName = String(render(cfg.action ?? '', { args, data }));
  const capturePattern = String(render(cfg.capture ?? '', { args, data }));
  const timeout = cfg.timeout ?? 5;
  const selectPath = cfg.select ? String(render(cfg.select, { args, data })) : null;
  const framework = cfg.framework ?? null;
  const actionArgs: unknown[] = cfg.args ?? [];

  if (!storeName || !actionName) throw new CliError('TAP_MISSING_PARAMS', 'tap: store and action are required');

  // Build select chain for the captured response
  const selectChain = selectPath
    ? selectPath.split('.').map((p: string) => `?.[${JSON.stringify(p)}]`).join('')
    : '';

  // Serialize action arguments
  const actionArgsRendered = actionArgs.map((a) => {
    const rendered = render(a, { args, data });
    return JSON.stringify(rendered);
  });
  const actionCall = actionArgsRendered.length
    ? `store[${JSON.stringify(actionName)}](${actionArgsRendered.join(', ')})`
    : `store[${JSON.stringify(actionName)}]()`;

  // Use shared interceptor generator for fetch/XHR patching
  const tap = generateTapInterceptorJs(JSON.stringify(capturePattern));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Add both store and action fields to the tap step config
  2. Verify the rendered values are non-empty (check that template args/data actually resolve)
  3. Confirm the store and action names match what the app registers

Example fix

// before
{ type: 'tap', store: 'cart', select: '.total', capture: '{{total}}' }
// after
{ type: 'tap', store: 'cart', action: 'addItem', select: '.total', capture: '{{total}}' }
Defensive patterns

Strategy: validation

Validate before calling

if (!cfg.store || !cfg.action) {
  throw new Error('tap step requires non-empty "store" and "action"');
}

Type guard

function hasTapParams(cfg: unknown): cfg is { store: string; action: string } & Record<string, unknown> {
  return typeof cfg === 'object' && cfg !== null
    && typeof (cfg as any).store === 'string' && (cfg as any).store.length > 0
    && typeof (cfg as any).action === 'string' && (cfg as any).action.length > 0;
}

Try / catch

try {
  await stepTap(cfg, args, data);
} catch (e) {
  if ((e as any).code === 'TAP_MISSING_PARAMS') {
    console.error('tap config invalid — set both store and action:', cfg);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling a tap step whose cfg is missing store (storeName falsy) or action (actionName falsy), or where the rendered values are empty strings. Any invocation of stepTap with partial config triggers this before any selector/timeout work begins.

Common situations: Copy-pasting a tap step and forgetting to fill in the action field, a template like render(cfg.store, ...) evaluating to an empty string because its args were absent, renaming a store/action in app code without updating the pipeline config.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/e0c8c26286d9d0b0. Report an issue: GitHub.