different-ai/openwork · error

command.template is required

Error message

command.template is required

What it means

serializeCommandFrontmatter() converts a command definition into markdown with YAML frontmatter for export/sync. The template (the command body) is mandatory: if command.template is missing, empty, or only whitespace after String()+trim(), it throws this error rather than writing an empty command file.

Source

Thrown at apps/desktop/electron/main.mjs:1250

}

function sanitizeCommandName(raw) {
  const trimmed = String(raw ?? "").trim().replace(/^\/+/, "");
  if (!trimmed) return null;
  const safe = Array.from(trimmed)
    .filter((char) => /[A-Za-z0-9_-]/.test(char))
    .join("");
  return safe || null;
}

function escapeYamlScalar(value) {
  return JSON.stringify(String(value ?? ""));
}

function serializeCommandFrontmatter(command) {
  const template = String(command?.template ?? "").trim();
  if (!template) {
    throw new Error("command.template is required");
  }

  let output = "---\n";
  if (typeof command?.description === "string" && command.description.trim()) {
    output += `description: ${escapeYamlScalar(command.description.trim())}\n`;
  }
  if (typeof command?.agent === "string" && command.agent.trim()) {
    output += `agent: ${escapeYamlScalar(command.agent.trim())}\n`;
  }
  if (typeof command?.model === "string" && command.model.trim()) {
    output += `model: ${escapeYamlScalar(command.model.trim())}\n`;
  }
  if (command?.subtask === true) {
    output += "subtask: true\n";
  }
  output += `---\n\n${template}\n`;
  return output;
}

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Set a non-empty template string on the command before export.
  2. Validate command objects with a schema (e.g. Zod) requiring template before serializing.
  3. Trim and check the template in the producing code path so empty commands never reach serialization.
  4. Fix the source file/config where the command was defined to restore its template.

Example fix

// before
await exportCommand({ name: 'deploy' }); // throws: no template
// after
await exportCommand({ name: 'deploy', template: 'pnpm deploy --prod' });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof command?.template !== 'string' || !command.template.trim()) {
  throw new TypeError('command.template must be a non-empty string');
}

Type guard

function hasTemplate(c) {
  return typeof c?.template === 'string' && c.template.trim().length > 0;
}

Try / catch

try {
  await serializeCommandFrontmatter(command);
} catch (err) {
  if (String(err.message) === 'command.template is required') {
    console.error('Skipping command with empty template:', command?.name);
  } else throw err;
}

Prevention

When it happens

Trigger: Exporting/writing a command whose object lacks a template field, has template: "" or " ", or passes null/undefined (command?.template ?? "" yields empty string).

Common situations: Manually authored command JSON missing the template key; an editor saved an empty template; deserialization dropping the field due to schema drift; importing commands from an older format.

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 different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/2b911843caef642d. Report an issue: GitHub.