paperclipai/paperclip · error

additional source localPath is not an absolute path: ${local

Error message

additional source localPath is not an absolute path: ${localPath}

What it means

Thrown while iterating input.additionalSources when a source's localPath is not a POSIX-absolute path. Additional (referenced) projects ride one confined directory sync each; because the confinement logic and the sync transport require an absolute source, a relative path is rejected before any transfer is attempted. The error is per-source and caught by the surrounding try block so other projects continue.

Source

Thrown at packages/adapter-utils/src/sandbox-managed-runtime.ts:1011

        progressBytes: assetTarSize,
      });
    }

    // Stage each referenced (additional) project as a plain, read-only tree in
    // its OWN isolated remote directory (`project-<projectId>`). An additional
    // project rides one confined `syncIn` directory mapping — a native directory
    // transfer, or the base64-tar fallback — with source and target confined to
    // their own roots. No workspace, git-history, or `.paperclip-runtime`
    // semantics apply; those stay anchor-only. Per-project failure isolation: one
    // project's confinement or sync failure logs a warning and is skipped, and
    // the run plus the other projects continue. Only a project that stages
    // successfully appears in `additionalSourceDirs`.
    for (const source of input.additionalSources ?? []) {
      const { localPath, projectId } = source;
      const label = `project-${projectId}`;
      try {
        if (!path.posix.isAbsolute(localPath)) {
          throw new Error(`additional source localPath is not an absolute path: ${localPath}`);
        }
        if (
          projectId.length === 0 ||
          projectId.includes("/") ||
          projectId.includes("\\") ||
          projectId.includes("..")
        ) {
          throw new Error(`additional source projectId is not a simple path segment: ${projectId}`);
        }
        const remoteProjectDir = path.posix.join(runtimeRootDir, label);
        await emitRuntimeStatus(input.onRuntimeProgress, "config_sync", "Syncing referenced project to sandbox");
        await stageConfinedSyncIn({
          files: [{
            sourcePath: localPath,
            targetPath: remoteProjectDir,
            kind: "directory",
            exclude: additionalSourceExclude,
            access: "ro",

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Resolve additionalSource.localPath with path.resolve() (or path.posix.resolve for remote-style) before passing it in.
  2. Validate localPath at the API boundary that collects additional sources.
  3. Confirm the source object came from a resolver that emits absolute paths, not a raw user string.
  4. Check the per-project failure is logged as a warning (the surrounding catch skips that project) and fix the offending entry.

Example fix

// before
additionalSources: [{ localPath: 'libs/shared', projectId: 'shared' }]
// after
additionalSources: [{ localPath: path.resolve(workspaceRoot, 'libs/shared'), projectId: 'shared' }]
Defensive patterns

Strategy: validation

Validate before calling

for (const s of additionalSources ?? []) {
  if (!path.posix.isAbsolute(s.localPath)) {
    throw new Error(`additionalSource localPath must be absolute: ${s.localPath}`);
  }
}

Type guard

function isAbsoluteLocalPath(p: string): boolean {
  return typeof p === 'string' && path.posix.isAbsolute(p);
}

Prevention

When it happens

Trigger: prepareSandboxManagedRuntime called with additionalSources containing an entry whose localPath lacks a leading slash (e.g. 'libs/shared' or './repo'). path.posix.isAbsolute returns false and this throws inside the per-project try.

Common situations: Caller passes a workspace-relative reference path instead of resolving it; a config field that should hold an absolute repo root was populated with a relative glob; cross-platform path handling produced a driveless path on the orchestrator.

Related errors


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