affaan-m/ECC · error · Error
launcherCommand must be a non-empty string
Error message
launcherCommand must be a non-empty string
What it means
renderTemplate validates that the launcherCommand template is a non-empty string before substituting {variable} placeholders. It throws when the template is undefined, empty, or whitespace-only. This is the entry-point guard for generating worker launcher commands in the tmux orchestrator.
Solutions
- Provide a non-empty launcherCommand template in the config, e.g. 'claude --task {task} --worktree {worktreePath}'.
- Check the config loading path for silently producing '' or undefined and add a load-time check.
- Fall back to a known-good default template when the config value is empty.
- Validate config with a schema (e.g. zod) requiring launcherCommand: z.string().min(1).
Example fix
// before
renderTemplate(config.launcherCommand, vars); // config.launcherCommand === ''
// after
const template = config.launcherCommand || 'claude --task {task}';
renderTemplate(template, vars); Defensive patterns
Strategy: validation
Validate before calling
if (typeof launcherCommand !== 'string' || launcherCommand.trim().length === 0) throw new Error('launcherCommand is required in config'); Type guard
const hasTemplate = (c) => typeof c?.launcherCommand === 'string' && c.launcherCommand.trim().length > 0;
Try / catch
try {
renderTemplate(template, vars);
} catch (e) {
if (String(e.message) === 'launcherCommand must be a non-empty string') {
console.error('launcherCommand missing/empty in orchestration config');
}
throw e;
} Prevention
- Require launcherCommand in the config schema with min length 1.
- Provide a default template constant for setups that omit it.
- Fail fast at config load, not at render time.
- Snapshot-test config parsing to catch empty-string regressions.
When it happens
Trigger: Calling renderTemplate(undefined, vars) or renderTemplate(' ', vars); passing config.launcherCommand when that config key was never set; spreading a config object where launcherCommand is absent.
Common situations: Omitting launcherCommand from the orchestration config; a config loader that returns an empty string on parse failure; renaming the config key so the template no longer reaches renderTemplate.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- buildOrchestrationPlan requires at least one worker
- seedPaths entries must stay inside repoRoot
- Template content must be a non-empty string
- template has unfilled placeholders
- Template name must be a non-empty string
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/6987e450e24f5170.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/tmux-worktree-orchestrator.js:18
'use strict';
const fs = require('fs');
const path = require('path');
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(' ');
}
View on GitHub (pinned to 8321021c54)