affaan-m/ECC · error · Error

Unknown template variable

Error message

Unknown template variable: ${key}

What it means

renderTemplate substitutes {key} placeholders in the launcher template and throws when the template references a variable key that is not present in the variables object. This stops half-rendered commands (with literal '{task}') from reaching the shell.

Solutions

  1. Add the missing key to the variables object passed to renderTemplate.
  2. Remove or correct the unknown placeholder in the template so it only uses supported keys.
  3. Check the renderTemplate replace regex/allowed keys and align template and variables.
  4. Log the variables object at call time to spot the mismatched key.

Example fix

// before
renderTemplate('run --task {task} --dir {dir}', { task: 'build' });
// after
renderTemplate('run --task {task} --dir {dir}', { task: 'build', dir: '/tmp/wt' });
Defensive patterns

Strategy: validation

Validate before calling

const required = [...template.matchAll(/\{([a-z_]+)\}/g)].map(m => m[1]);
const missing = required.filter(k => !(k in variables));
if (missing.length) throw new Error(`Missing template variables: ${missing.join(',')}`);

Type guard

const hasAllVars = (t, v) => [...t.matchAll(/\{([a-z_]+)\}/g)].every(m => m[1] in v);

Try / catch

try {
  const cmd = renderTemplate(template, vars);
} catch (e) {
  if (String(e.message).startsWith('Unknown template variable')) {
    console.error('Template/variables mismatch:', e.message, Object.keys(vars));
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling renderTemplate('claude --task {task} --root {root}', { task }) where 'root' is not in variables; renaming a placeholder in the template without updating the supplied variables map; a typo like {taskname} vs {taskName}.

Common situations: Editing the launcher command string in config to add a new placeholder without extending the variables passed by the orchestrator; case-sensitivity mistakes; copying a template from docs that uses variables this version doesn't support.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/a042825c44114fa5. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/tmux-worktree-orchestrator.js:23

const { spawnSync } = require('child_process');

function slugify(value, fallback = 'worker') {
  const normalized = String(value || '')
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '');
  return normalized || fallback;
}

function renderTemplate(template, variables) {
  if (typeof template !== 'string' || template.trim().length === 0) {
    throw new Error('launcherCommand must be a non-empty string');
  }

  return template.replace(/\{([a-z_]+)\}/g, (match, key) => {
    if (!(key in variables)) {
      throw new Error(`Unknown template variable: ${key}`);
    }
    return String(variables[key]);
  });
}

function shellQuote(value) {
  return `'${String(value).replace(/'/g, `'\\''`)}'`;
}

function formatCommand(program, args) {
  return [program, ...args.map(shellQuote)].join(' ');
}

function buildTemplateVariables(values) {
  return Object.entries(values).reduce((accumulator, [key, value]) => {
    const stringValue = String(value);
    const quotedValue = shellQuote(stringValue);

View on GitHub (pinned to 8321021c54)