different-ai/openwork · error · ApiError

invalid_command_template

invalid_command_template

Error message

Command template is required

What it means

buildCommandContent validates that an upsert-command payload includes a non-empty template before writing the command's markdown frontmatter. An empty or whitespace-only template is rejected with a 400 ApiError.

Source

Thrown at apps/server/src/commands.ts:80

  if (scope === "global") {
    const dir = join(homedir(), ".config", "opencode", "commands");
    return listCommandsInDir(dir, "global");
  }
  return listCommandsInDir(projectCommandsDir(workspaceRoot), "workspace");
}

export type UpsertCommandPayload = {
  name: string;
  description?: string;
  template: string;
  agent?: string;
  model?: string | null;
  subtask?: boolean;
};

export function buildCommandContent(payload: UpsertCommandPayload): { name: string; content: string } {
  if (!payload.template || payload.template.trim().length === 0) {
    throw new ApiError(400, "invalid_command_template", "Command template is required");
  }
  const sanitized = sanitizeCommandName(payload.name);
  validateCommandName(sanitized);
  const frontmatter = buildFrontmatter(normalizeCommandFrontmatter({
    name: sanitized,
    description: payload.description,
    agent: payload.agent,
    model: payload.model,
    subtask: payload.subtask ?? false,
  }));
  const content = frontmatter + "\n" + payload.template.trim() + "\n";
  return { name: sanitized, content };
}

export async function upsertCommand(
  workspaceRoot: string,
  payload: UpsertCommandPayload,
): Promise<string> {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Include a non-empty template string in the payload before calling the upsert endpoint
  2. Trim-check the template on the client before submitting and show a form validation error
  3. If migrating from an older API version, add the template field that is now required

Example fix

// before
await api.upsertCommand({ name: "deploy", description: "Deploy the app" });
// after
await api.upsertCommand({ name: "deploy", description: "Deploy the app", template: "Run the deploy pipeline for $ARGUMENTS" });
Defensive patterns

Strategy: validation

Validate before calling

const parsed = UpsertSchema.safeParse(payload); if (!parsed.success) throw new Error(parsed.error.issues[0].message);

Prevention

When it happens

Trigger: Calling the command upsert API (or buildCommandContent directly) with payload.template omitted, null, or set to "" / " ".

Common situations: Client form submitted without filling the prompt body; API client sends only name/description; older clients predating a template-required schema change; JSON body missing the field due to serialization bugs.

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/ea4159d311acf575. Report an issue: GitHub.