paperclipai/paperclip · error · Error

${label} is not a regular file at ${canonical}.

Error message

${label} is not a regular file at ${canonical}.

What it means

After resolving successfully, canonicalRegularFile() lstats the canonical path and finds it is not a regular file (a directory, FIFO, socket, or device). Config paths must be plain files because the loader reads them as JSON, so anything else is rejected before parsing.

Source

Thrown at packages/shared/src/worktree-seed-source.ts:109

      );
    }
  }
  return false;
}

function canonicalRegularFile(filePath: string, label: string): string {
  const resolved = path.resolve(filePath);
  let canonical: string;
  try {
    canonical = realpathSync(resolved);
  } catch {
    throw new Error(`${label} does not exist at ${resolved}.`);
  }
  if (canonical !== resolved || lstatSync(resolved).isSymbolicLink()) {
    throw new Error(`${label} must be a canonical path and cannot use a symlink alias.`);
  }
  if (!lstatSync(canonical).isFile()) {
    throw new Error(`${label} is not a regular file at ${canonical}.`);
  }
  return canonical;
}

/** Resolve the authoritative source and target identities without consulting diagnostics. */
export function resolveRegisteredWorktreeSeedSource(
  input: RegisteredWorktreeSeedSourceInput,
): CanonicalWorktreeSeedSource {
  const registeredCwd = input.registeredBaseWorkspaceCwd?.trim();
  const explicitSource = input.explicitSourceConfigPath?.trim();
  if (!registeredCwd && !explicitSource) {
    throw new Error(
      "Worktree seed source is not registered. Managed boot requires a project workspace; manual boot requires --from-config.",
    );
  }

  let canonicalBaseCwd: string | null = null;
  let registeredConfigPath: string | null = null;

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Verify with `ls -la <resolved>` and `file <resolved>` what actually sits at the path.
  2. Point the call at the real config file (`<...>/.paperclip/config.json`), not its directory.
  3. If a directory/FIFO was created by mistake, remove it and restore a regular config.json file.

Example fix

# before
paperclip worktree seed --from-config ~/.paperclip/instances/myid   # directory

# after
paperclip worktree seed --from-config ~/.paperclip/instances/myid/config.json
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from "node:fs";

function assertRegularConfigFile(p: string): void {
  const st = statSync(p); // throws ENOENT if absent — handle first
  if (!st.isFile()) throw new Error(`${p} is not a regular file`);
}

Type guard

const isRegularFile = (p: string): boolean => {
  try { return require("node:fs").statSync(p).isFile(); } catch { return false; }
};

Try / catch

try {
  resolveRegisteredWorktreeSeedSource(input);
} catch (e) {
  if (e instanceof Error && /not a regular file/.test(e.message)) {
    // path pointed at a directory/special node — fix the path, not retryable
  } else throw e;
}

Prevention

When it happens

Trigger: A config path pointing at a directory (e.g. passing `.../.paperclip` instead of `.../.paperclip/config.json`); a config path occupied by a named pipe or socket created by tooling; /dev or other special nodes given as --from-config.

Common situations: Truncated path in scripts or shell history (dropping the `config.json` segment); mount points or bind mounts placed over the config location; a directory created where a file was expected by a mis-written provisioning step.

Related errors


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-21). Data as JSON: /api/errors/794337da629741b5. Report an issue: GitHub.