jackwener/OpenCLI · error · ArgumentError

No cost model is defined for action "${operation}"

Error message

No cost model is defined for action "${operation}"

What it means

estimateAction ends with a catch-all: if the operation is not free (open-editor/cancel), not a video rerun, not omni-related, not in ACTION_COSTS, and not one of the six video actions, no cost model exists and this ArgumentError is thrown.

Source

Thrown at clis/midjourney/capabilities.js:313

  if (!ACTION_CHOICES.includes(operation)) {
    throw new ArgumentError(`operation must be one of: ${ACTION_CHOICES.join(', ')}`);
  }
  if (operation === 'open-editor' || operation === 'cancel') return 0;
  if (operation === 'rerun' && sourceIsVideo) {
    if (!['sd', 'hd'].includes(videoResolution)) throw new ArgumentError('--video-resolution must be sd or hd');
    if (![1, 2, 4].includes(batchSize)) throw new ArgumentError('--batch-size must be 1, 2, or 4');
    return GPU_COST_MINUTES[`video${videoResolution === 'hd' ? 'Hd' : 'Sd'}${batchSize}`];
  }
  if (sourceUsesOmni && ['rerun', 'vary-subtle', 'vary-strong'].includes(operation)) {
    return GPU_COST_MINUTES.omni;
  }
  if (Object.prototype.hasOwnProperty.call(ACTION_COSTS, operation)) return ACTION_COSTS[operation];
  if (['animate-low', 'animate-high', 'loop-low', 'loop-high', 'extend-low', 'extend-high'].includes(operation)) {
    if (!['sd', 'hd'].includes(videoResolution)) throw new ArgumentError('--video-resolution must be sd or hd');
    if (![1, 2, 4].includes(batchSize)) throw new ArgumentError('--batch-size must be 1, 2, or 4');
    return GPU_COST_MINUTES[`video${videoResolution === 'hd' ? 'Hd' : 'Sd'}${batchSize}`];
  }
  throw new ArgumentError(`No cost model is defined for action "${operation}"`);
}

export function assertActionPlan(account, operation, { videoResolution = 'sd' } = {}) {
  const capabilities = planCapabilities(account);
  if (videoResolution === 'hd' && !capabilities.canHdVideo
    && ['animate-low', 'animate-high', 'loop-low', 'loop-high', 'extend-low', 'extend-high'].includes(operation)) {
    throw new ArgumentError(`${capabilities.plan || 'current'} plan does not support HD video; use --video-resolution sd`);
  }
  return capabilities;
}

export function buildEffectivePrompt(prompt, plan, args, remoteReferences = {}) {
  let result = String(prompt || '').trim();
  const imageUrls = remoteReferences.image || [];
  if (imageUrls.length) result = `${imageUrls.join(' ')} ${result}`.trim();

  const additions = [];
  if (!promptParamValue(result, ['v', 'version']) && !promptParamValue(result, ['niji']) && args.model && args.model !== 'auto') {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Add an entry for the operation to ACTION_COSTS (or a cost branch) in capabilities.js
  2. Use an operation that already has a cost model (listed in the error)
  3. Align ACTION_CHOICES and cost tables in the same change/PR
  4. Add a unit test asserting every ACTION_CHOICES entry has a resolvable cost

Example fix

// before
// ACTION_CHOICES includes 'upscale-x' but ACTION_COSTS does not
estimateAction('upscale-x', opts);
// after
const ACTION_COSTS = { ..., 'upscale-x': 2 }; // define the cost
estimateAction('upscale-x', opts);
Defensive patterns

Strategy: validation

Validate before calling

import { ACTION_CHOICES, ACTION_COSTS } from './clis/midjourney/capabilities.js';
if (!Object.prototype.hasOwnProperty.call(ACTION_COSTS, operation)) {
  throw new Error(`no cost model for "${operation}"; add it to ACTION_COSTS or use a supported action`);
}
const minutes = estimateAction(operation, opts);

Type guard

function hasCostModel(op) {
  return typeof op === 'string' && Object.prototype.hasOwnProperty.call(ACTION_COSTS, op);
}

Try / catch

try {
  const minutes = estimateAction(operation, opts);
} catch (err) {
  if (err instanceof ArgumentError && /No cost model is defined/.test(err.message)) {
    console.error(`Action "${operation}" lacks a cost model; pick a supported action or update ACTION_COSTS`);
  } else throw err;
}

Prevention

When it happens

Trigger: estimateAction with an operation that is in ACTION_CHOICES but has no cost branch — typically after ACTION_CHOICES was extended without adding a matching ACTION_COSTS entry or cost branch.

Common situations: Adding a new action to ACTION_CHOICES only (partial feature wiring); refactoring that removed an ACTION_COSTS key; callers passing internal action names that are intentionally unsupported for estimation.

Related errors


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