{"record":{"id":"a042825c44114fa5","repo":"affaan-m/ECC","slug":"unknown-template-variable-key","errorCode":null,"errorMessage":"Unknown template variable: ${key}","messagePattern":"Unknown template variable: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/tmux-worktree-orchestrator.js","lineNumber":23,"sourceCode":"const { spawnSync } = require('child_process');\n\nfunction slugify(value, fallback = 'worker') {\n  const normalized = String(value || '')\n    .trim()\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, '-')\n    .replace(/^-+|-+$/g, '');\n  return normalized || fallback;\n}\n\nfunction renderTemplate(template, variables) {\n  if (typeof template !== 'string' || template.trim().length === 0) {\n    throw new Error('launcherCommand must be a non-empty string');\n  }\n\n  return template.replace(/\\{([a-z_]+)\\}/g, (match, key) => {\n    if (!(key in variables)) {\n      throw new Error(`Unknown template variable: ${key}`);\n    }\n    return String(variables[key]);\n  });\n}\n\nfunction shellQuote(value) {\n  return `'${String(value).replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction formatCommand(program, args) {\n  return [program, ...args.map(shellQuote)].join(' ');\n}\n\nfunction buildTemplateVariables(values) {\n  return Object.entries(values).reduce((accumulator, [key, value]) => {\n    const stringValue = String(value);\n    const quotedValue = shellQuote(stringValue);\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/tmux-worktree-orchestrator.js#L5-L41","documentation":"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.","triggerScenarios":"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}.","commonSituations":"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.","solutions":["Add the missing key to the variables object passed to renderTemplate.","Remove or correct the unknown placeholder in the template so it only uses supported keys.","Check the renderTemplate replace regex/allowed keys and align template and variables.","Log the variables object at call time to spot the mismatched key."],"exampleFix":"// before\nrenderTemplate('run --task {task} --dir {dir}', { task: 'build' });\n// after\nrenderTemplate('run --task {task} --dir {dir}', { task: 'build', dir: '/tmp/wt' });","handlingStrategy":"validation","validationCode":"const required = [...template.matchAll(/\\{([a-z_]+)\\}/g)].map(m => m[1]);\nconst missing = required.filter(k => !(k in variables));\nif (missing.length) throw new Error(`Missing template variables: ${missing.join(',')}`);","typeGuard":"const hasAllVars = (t, v) => [...t.matchAll(/\\{([a-z_]+)\\}/g)].every(m => m[1] in v);","tryCatchPattern":"try {\n  const cmd = renderTemplate(template, vars);\n} catch (e) {\n  if (String(e.message).startsWith('Unknown template variable')) {\n    console.error('Template/variables mismatch:', e.message, Object.keys(vars));\n  }\n  throw e;\n}","preventionTips":["Extract placeholders from the template and assert the variables superset before rendering.","Keep template and variables construction adjacent in code.","Avoid mixing camelCase and snake_case keys.","Document the supported placeholder set next to the config."],"tags":["template","variables","tmux"],"backgroundTag":"missing-required-argument","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}