paperclipai/paperclip · error · Error

Refusing to replace non-regular shim ${paths.shimPath}.

Error message

Refusing to replace non-regular shim ${paths.shimPath}.

What it means

Thrown by assertManagedShimWritable when paths.shimPath exists but is not a regular file (it is a symlink, socket, device node, or other special file). The installer must only overwrite its own regular-file shim; refusing to replace a non-regular file prevents clobbering symlinks, sockets, or other special objects that a user may have intentionally placed at that path.

Source

Thrown at cli/src/install-store.ts:364

    }
  }
  return removed;
}

export function assertManagedShimWritable(paths = resolveInstallStorePaths()): void {
  const homeDir = path.dirname(path.dirname(path.dirname(paths.shimPath)));
  for (const directoryPath of [homeDir, path.join(homeDir, ".local"), path.dirname(paths.shimPath)]) {
    if (!fs.existsSync(directoryPath)) continue;
    const directoryStat = fs.lstatSync(directoryPath);
    if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) {
      throw new Error(`Refusing to use unsafe shim directory ${directoryPath}.`);
    }
    assertOwnedByCurrentUser(directoryStat, directoryPath);
  }
  try {
    const stat = fs.lstatSync(paths.shimPath);
    if (!stat.isFile() || stat.isSymbolicLink()) {
      throw new Error(`Refusing to replace non-regular shim ${paths.shimPath}.`);
    }
    assertOwnedByCurrentUser(stat, paths.shimPath);
    if (stat.nlink > 1) throw new Error(`Refusing to replace multiply linked shim ${paths.shimPath}.`);
    const existing = fs.readFileSync(paths.shimPath, "utf8");
    if (!isManagedShimContents(existing)) {
      throw new Error(`Refusing to replace existing non-managed command ${paths.shimPath}.`);
    }
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
  }
}

function shellQuote(value: string): string {
  return `'${value.replace(/'/g, `'"'"'`)}'`;
}

function isManagedShimContents(contents: string): boolean {
  const lines = contents.split("\n");

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Inspect the shim: 'ls -la ~/.local/bin/paperclipai' to see its type.
  2. If it is a symlink to an unmanaged binary, remove it so the installer can create its managed shim: 'rm ~/.local/bin/paperclipai'.
  3. If it is a symlink to the correct managed location, resolve the real path and verify it matches the expected shim format, then remove the symlink.
  4. Re-run the install to write a fresh regular-file shim.

Example fix

// before: shim is a symlink
// ls -la ~/.local/bin/paperclipai -> lrwxrwxrwx -> /opt/paperclip/bin/paperclipai

// after: remove symlink so installer writes a regular file
// rm ~/.local/bin/paperclipai
// re-run: paperclipai install
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';

function isShimRegularFile(shimPath: string): boolean {
  try {
    const stat = fs.lstatSync(shimPath);
    return stat.isFile() && !stat.isSymbolicLink();
  } catch (error) {
    return (error as NodeJS.ErrnoException).code === 'ENOENT';
  }
}

// Call before writeManagedShim:
if (!isShimRegularFile(paths.shimPath)) {
  console.warn('Existing shim is not a regular file; removing it before install.');
  fs.rmSync(paths.shimPath, { force: true });
}

Try / catch

try {
  writeManagedShim(paths);
} catch (error) {
  if (error instanceof Error && error.message.includes('non-regular shim')) {
    // The shim path is a symlink or special file; back it up and remove
    fs.renameSync(paths.shimPath, `${paths.shimPath}.bak`);
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling assertManagedShimWritable or writeManagedShim when ~/.local/bin/paperclipai exists but is a symlink, named pipe, socket, device file, or any non-regular-file type.

Common situations: A user or package manager created ~/.local/bin/paperclipai as a symlink to another binary. A dotfile manager symlinked the shim. A different tool placed a non-file object at that path.

Related errors


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