paperclipai/paperclip · error · Error

Source path or URL is required.

Error message

Source path or URL is required.

What it means

Thrown at the top of the `company import <fromPathOrUrl>` action when the positional argument, after `.trim()`, is the empty string. It is a pure input-validation guard that runs before any API call or filesystem check. Commander passes the positional as the first action parameter; an empty/whitespace value triggers this.

Source

Thrown at cli/src/commands/client/company.ts:1665

      .option("--target <mode>", "Target mode: new | existing")
      .option("-C, --company-id <id>", "Existing target company ID")
      .option("--new-company-name <name>", "Name override for --target new")
      .option("--agents <list>", "Comma-separated agent slugs to import, or all", "all")
      .option("--collision <mode>", "Collision strategy: rename | skip | replace", "rename")
      .option("--ref <value>", "Git ref to use for GitHub imports (branch, tag, or commit)")
      .option("--paperclip-url <url>", "Alias for --api-base on this command")
      .option("--yes", "Accept default selection and skip the pre-import confirmation prompt", false)
      .option("--dry-run", "Run preview only without applying", false)
      .action(async (fromPathOrUrl: string, opts: CompanyImportOptions) => {
        try {
          if (!opts.apiBase?.trim() && opts.paperclipUrl?.trim()) {
            opts.apiBase = opts.paperclipUrl.trim();
          }
          const ctx = resolveCommandContext(opts);
          const interactiveView = isInteractiveTerminal() && !ctx.json;
          const from = fromPathOrUrl.trim();
          if (!from) {
            throw new Error("Source path or URL is required.");
          }

          const include = resolveImportInclude(opts.include);
          const agents = parseAgents(opts.agents);
          const collision = (opts.collision ?? "rename").toLowerCase() as CompanyCollisionMode;
          if (!["rename", "skip", "replace"].includes(collision)) {
            throw new Error("Invalid --collision value. Use: rename, skip, replace");
          }

          const inferredTarget = opts.target ?? (opts.companyId || ctx.companyId ? "existing" : "new");
          const target = inferredTarget.toLowerCase() as CompanyImportTargetMode;
          if (!["new", "existing"].includes(target)) {
            throw new Error("Invalid --target value. Use: new | existing");
          }

          const existingTargetCompanyId = opts.companyId?.trim() || ctx.companyId;
          const targetPayload =
            target === "existing"

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Provide a non-empty source: a local directory path or a GitHub repo URL, e.g. `paperclipai company import ./my-export`.
  2. When scripting, guard the variable: `[ -n "$SRC" ] || { echo 'source missing'; exit 1; }` before invoking the CLI.
  3. Check Commander argument parsing — ensure flags use `=` or space syntax that does not swallow the positional.

Example fix

# before
paperclipai company import "$IMPORT_SOURCE"
# after
SRC="${IMPORT_SOURCE:-./company-export}"
[ -n "$SRC" ] || { echo 'source required'; exit 1; }
paperclipai company import "$SRC"
Defensive patterns

Strategy: validation

Validate before calling

function resolveImportSource(raw: string | undefined): string {
  const src = (raw ?? "").trim();
  if (!src) throw new Error("Import source (local path or GitHub URL) is required");
  return src;
}
// Usage before exec:
const src = resolveImportSource(process.env.IMPORT_SOURCE);

Type guard

function isNonEmptySource(v: unknown): v is string {
  return typeof v === "string" && v.trim().length > 0;
}

Prevention

When it happens

Trigger: Running `paperclipai company import` with no positional argument; passing an empty string or whitespace-only argument (e.g. `paperclipai company import ""`); a script that interpolates an unset shell variable as the source.

Common situations: Copy-pasting a command template but forgetting to fill in the path/URL; a CI job referencing `$IMPORT_SOURCE` when the env var is unset; mistyping the argument order so flags consume the positional slot.

Related errors


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