paperclipai/paperclip · error · Error

Skill reference is required.

Error message

Skill reference is required.

What it means

Thrown by resolveCompanySkillReference() when the reference string is empty after trimming. This shared resolver backs every company-skill operation (show, files, update, reset, remove, audit, agent sync). It guards up front because all downstream lookups (by id, key, slug) would otherwise be no-ops.

Source

Thrown at cli/src/commands/client/skills.ts:611

async function getCatalogSkill(ctx: ResolvedClientContext, catalogRef: string): Promise<CatalogSkill> {
  const ref = catalogRef.trim();
  if (!ref) {
    throw new Error("Catalog skill reference is required.");
  }
  const detail = await ctx.api.get<CatalogSkill>(`/api/skills/catalog/ref?ref=${encodeURIComponent(ref)}`);
  if (!detail) {
    throw new Error(`Catalog skill not found: ${catalogRef}`);
  }
  return detail;
}

export function resolveCompanySkillReference(
  skills: CompanySkillReferenceTarget[],
  reference: string,
): CompanySkillReferenceTarget {
  const trimmed = reference.trim();
  if (!trimmed) {
    throw new Error("Skill reference is required.");
  }

  const byId = skills.find((skill) => skill.id === trimmed);
  if (byId) return byId;

  const byKey = skills.find((skill) => skill.key === trimmed);
  if (byKey) return byKey;

  const normalizedSlug = normalizeSkillSlug(trimmed);
  const bySlug = skills.filter((skill) => skill.slug === normalizedSlug);
  if (bySlug.length === 1 && bySlug[0]) return bySlug[0];
  if (bySlug.length > 1) {
    throw new Error(`Ambiguous skill slug "${trimmed}". Use a skill ID or key instead.`);
  }

  throw new Error(`Skill not found: ${reference}`);
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Supply a non-empty company skill ID, key, or unique slug as the positional argument.
  2. If resolving dynamically, list company skills first (`skills list`) and feed a concrete id/key.
  3. Trim and validate the value in your wrapper script before calling the CLI.

Example fix

// before
await run(["skills", "show", refFromUser]);
// after
const ref = (refFromUser ?? "").trim();
if (!ref) throw new Error("skillRef is required");
await run(["skills", "show", ref]);
Defensive patterns

Strategy: validation

Validate before calling

const ref = (skillRef ?? "").trim();
if (!ref) {
  throw new Error("skillRef is required for this command");
}

Type guard

function isNonEmptyRef(ref: string | undefined): ref is string {
  return typeof ref === "string" && ref.trim().length > 0;
}

Prevention

When it happens

Trigger: Any company-scoped skills command with a blank positional `<skillRef>`: `paperclipai skills show ""`, `skills remove " "`, or an agent sync where the resolver is invoked with empty input.

Common situations: Unset environment variable expanded into the positional arg, programmatic callers forgetting to supply a ref, or trailing whitespace from a list-parse step.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/de0ef3252b53a4e8. Report an issue: GitHub.