paperclipai/paperclip · error · Error

Source and target Paperclip configs are the same canonical f

Error message

Source and target Paperclip configs are the same canonical file.

What it means

resolveRegisteredWorktreeSeedSource canonicalizes both the source config and the target worktree config and found them identical: the seed operation's destination is the same file as its source. Seeding would overwrite its own origin, so the invariant check rejects it.

Source

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

  }
  const canonicalSourceConfigPath = canonicalRegularFile(selectedPath, "Registered source Paperclip config");
  if (registeredConfigPath && canonicalSourceConfigPath !== registeredConfigPath) {
    throw new Error("Registered source Paperclip config escapes the base project workspace or uses a symlink alias.");
  }

  if (explicitSource) {
    const canonicalExplicitSource = canonicalRegularFile(explicitSource, "Explicit source Paperclip config");
    if (canonicalExplicitSource !== canonicalSourceConfigPath) {
      throw new Error("Explicit source Paperclip config does not match the registered base project workspace.");
    }
  }

  const canonicalTargetConfigPath = canonicalRegularFile(
    input.targetConfigPath,
    "Target worktree Paperclip config",
  );
  if (canonicalSourceConfigPath === canonicalTargetConfigPath) {
    throw new Error("Source and target Paperclip configs are the same canonical file.");
  }

  const sourceInstanceId = readInstanceId(canonicalSourceConfigPath, "source");
  const targetInstanceId = readInstanceId(canonicalTargetConfigPath, "target");
  if (targetInstanceId !== input.expectedTargetInstanceId) {
    throw new Error("Target Paperclip instance does not match the registered worktree instance.");
  }
  if (sourceInstanceId === targetInstanceId) {
    throw new Error("Source and target Paperclip configs name the same instance.");
  }

  return {
    baseWorkspaceCwd: canonicalBaseCwd,
    configPath: canonicalSourceConfigPath,
    instanceId: sourceInstanceId,
    targetConfigPath: canonicalTargetConfigPath,
    targetInstanceId,
  };

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Run the command from the new worktree directory (or pass its path) so the target config is the worktree's own, not the base's.
  2. Verify `realpath <target>/.paperclip/config.json` differs from the source config.
  3. If --from-config was meant to seed this worktree, make sure the worktree's own config.json path is the target, not the source file.

Example fix

# before (run inside the base workspace)
paperclip worktree seed --from-config ./.paperclip/config.json   # target == source

# after (run inside the new worktree)
cd ../worktrees/issue-42 && paperclip worktree seed --from-config "$(realpath ../../base/.paperclip/config.json)"
Defensive patterns

Strategy: validation

Validate before calling

import { realpathSync } from "node:fs";

const src = realpathSync(sourceConfigPath);
const dst = realpathSync(targetConfigPath);
if (src === dst) throw new Error("refusing to seed a worktree onto itself");

Type guard

const isDistinctTarget = (src: string, dst: string): boolean => {
  try { return realpathSync(src) !== realpathSync(dst); } catch { return false; }
};

Prevention

When it happens

Trigger: Running worktree seed from inside the base workspace with the target worktree path resolving to the base itself; passing --from-config equal to the target worktree's config; a target cwd that symlinks back to the base (both canonicalize to one path).

Common situations: Invoking the seed command in the wrong directory (base instead of the new worktree); CI scripts reusing `$PWD` for both source and target; misconfigured worktree root pointing at the checkout root.

Related errors


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