paperclipai/paperclip · error · Error
Registered base project workspace Paperclip config at ${conf
Error message
Registered base project workspace Paperclip config at ${configPath} cannot be inspected (${errorCode(error)}${detail ?? ""}). What it means
Thrown by inspectDeclaredEntry in worktree-seed-source.ts when lstatSync on the declared config path (or the .paperclip directory entry) fails with any code other than ENOENT. Absent entries are fine (returns null); unreadable, malformed, or looping entries (EACCES, EPERM, ENOTDIR, ELOOP, EMFILE) mean the declared source cannot be verified, and the resolver fails closed rather than silently seeding from a different instance.
Source
Thrown at packages/shared/src/worktree-seed-source.ts:62
throw new Error(`Registered ${label} Paperclip config has no PAPERCLIP_INSTANCE_ID binding.`);
}
function errorCode(error: unknown): string {
return (error as NodeJS.ErrnoException | null)?.code ?? "unknown error";
}
/**
* Inspect a directory entry without following it, returning null only when it is absent.
*
* Any other failure means the declared path is unreadable or malformed, and a guess there
* would silently seed from a different instance.
*/
function inspectDeclaredEntry(entryPath: string, configPath: string, detail?: string): Stats | null {
try {
return lstatSync(entryPath);
} catch (error) {
if (errorCode(error) === "ENOENT") return null;
throw new Error(
`Registered base project workspace Paperclip config at ${configPath} cannot be inspected (${errorCode(error)}${detail ?? ""}).`,
);
}
}
/**
* Whether a base project workspace declares an instance config of its own.
*
* This tests directory entries and does not follow them. A dangling or aliased symlink,
* at the config itself or at the `.paperclip` directory holding it, still counts as a
* declared config, so the resolver rejects the malformed source instead of falling back
* to another one.
*/
export function baseWorkspaceDeclaresInstanceConfig(baseWorkspaceCwd: string): boolean {
const configDir = path.join(baseWorkspaceCwd, ".paperclip");
const configPath = path.join(configDir, "config.json");
if (inspectDeclaredEntry(configPath, configPath)) return true;
View on GitHub (pinned to a7e689b3c3)
Solutions
- Read the errno in the message: EACCES/EPERM -> fix ownership/permissions on the workspace and every parent (chmod/chown so the process can lstat); ENOTDIR -> a path component is a file, correct the layout; ELOOP -> remove the symlink loop on .paperclip or the config; EMFILE -> raise the FD limit.
- Verify with: ls -la <workspace>/.paperclip and namei -l <workspace>/.paperclip/config.json to see where traversal breaks.
- Run the command as the user that owns the workspace, or grant that user read+execute (search) permission on the path.
- Replace a symlinked .paperclip with a real directory if the link target is missing or cyclic.
Example fix
# before: .paperclip is a symlink loop ln -s .paperclip .paperclip # accidental self-link # after rm <workspace>/.paperclip && mkdir <workspace>/.paperclip # then re-create or restore config.json inside it
Defensive patterns
Strategy: validation
Validate before calling
import fs from "node:fs";
function workspaceInspectable(workspace: string): boolean {
const entries = [workspace, path.join(workspace, ".paperclip"), path.join(workspace, ".paperclip", "config.json")];
try {
entries.forEach((p) => fs.lstatSync(p));
return true;
} catch {
return false;
}
} Try / catch
try {
resolveRegisteredWorktreeSeedSource(input);
} catch (error) {
if (error instanceof Error && error.message.includes("cannot be inspected")) {
// parse the errno in the message: EACCES -> fix perms/owner; ENOTDIR/ELOOP -> fix layout/symlink; EMFILE -> raise FD limit
}
throw error;
} Prevention
- Run workspace operations as the user who owns the workspace tree.
- Ensure search (execute) permission on every parent of .paperclip/config.json.
- Avoid symlinked .paperclip directories, especially dangling or cyclic ones.
- After restores/chowns, verify with namei -l <workspace>/.paperclip/config.json.
When it happens
Trigger: resolveRegisteredWorktreeSeedSource probes <baseWorkspace>/.paperclip/config.json or the .paperclip entry: a permission-denied home/workspace directory yields EACCES; a path component that is a file yields ENOTDIR; a symlink cycle on .paperclip yields ELOOP; FD exhaustion yields EMFILE.
Common situations: Workspaces under directories owned by another user or with restrictive modes (e.g. after chown/restore from archive); .paperclip accidentally created as a file, or a parent of it; self-referential symlinks left by broken dotfile managers; running as a different user/service account than the one that created the workspace.
Related errors
- Registered ${label} Paperclip config is missing its adjacent
- Failed to create a pending worktree seed manifest.
- Registered ${label} Paperclip config has no PAPERCLIP_INSTAN
- Plugin UI directory not found
- Import cancelled.
AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-21).
Data as JSON: /api/errors/c4518ef6904ced2b.
Report an issue: GitHub.