different-ai/openwork · error

name is required

Error message

name is required

What it means

deleteCommandFile sanitizes the name argument before constructing the <name>.md path inside the commands directory. If name is missing/empty or sanitizes to nothing, it throws 'name is required' to avoid deleting an undefined or dangerous path.

Source

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

    .sort();
}

async function writeCommandFile(scope, projectDir, command) {
  const safeName = sanitizeCommandName(command?.name);
  if (!safeName) {
    throw new Error("command.name is required");
  }
  const commandsDir = resolveCommandsDir(scope, projectDir);
  await mkdir(commandsDir, { recursive: true });
  const filePath = path.join(commandsDir, `${safeName}.md`);
  await writeFile(filePath, serializeCommandFrontmatter({ ...command, name: safeName }), "utf8");
  return execResult(true, `Wrote ${filePath}`);
}

async function deleteCommandFile(scope, projectDir, name) {
  const safeName = sanitizeCommandName(name);
  if (!safeName) {
    throw new Error("name is required");
  }
  const commandsDir = resolveCommandsDir(scope, projectDir);
  const filePath = path.join(commandsDir, `${safeName}.md`);
  if (await pathExists(filePath)) {
    await rm(filePath, { force: true });
  }
  return execResult(true, `Deleted ${filePath}`);
}

async function collectProjectSkillRoots(projectDir) {
  const roots = [];
  let current = path.resolve(projectDir);

  while (true) {
    const opencodeSkills = path.join(current, ".opencode", "skills");
    const legacySkills = path.join(current, ".opencode", "skill");
    const claudeSkills = path.join(current, ".claude", "skills");

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Pass the exact command name as it appears in the commands directory listing.
  2. Verify the delete handler actually forwards the name (not an event object or index).
  3. Trim and sanity-check the name is non-empty before invoking.
  4. Re-list commands (listCommandNames) and delete using a fresh, valid name.

Example fix

// before
await deleteCommandFile("workspace", dir, undefined);
// after
await deleteCommandFile("workspace", dir, "run-tests");
Defensive patterns

Strategy: validation

Validate before calling

const safe = String(name ?? '').trim();
if (!safe || /[\\/]/.test(safe)) {
  throw new Error('name must be a non-empty filename-safe string');
}

Type guard

function isDeletableCommandName(name) {
  return typeof name === 'string' && name.trim().length > 0;
}

Prevention

When it happens

Trigger: Calling the command-delete API with name=undefined/null/empty string, or a name made only of characters stripped by sanitizeCommandName (slashes, whitespace).

Common situations: Deleting from a stale list where the command row lost its name, passing the command's display label (stripped to nothing) instead of its filename-safe name, or wiring the delete handler without binding the name argument.

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