paperclipai/paperclip · error

filesystemExtraPaths[${index}] must use access "ro" or "rw"

Error message

filesystemExtraPaths[${index}] must use access "ro" or "rw" and an absolute path.

What it means

Thrown by parseLocalProcessSandboxExtraPaths when an entry passed the shape check (it is a plain object) but its access field is something other than "ro", "rw", or null/undefined, OR its path field is missing or not a string. The access normalization at local-process-sandbox.ts:503 produces null for any other literal; combined with a missing/non-string path, the entry is rejected.

Source

Thrown at packages/adapter-utils/src/local-process-sandbox.ts:505

  }

  args.push("--chdir", cwd, "--", executable, ...executableArgs);
  return { command: bwrapCommand, args, cwd: "/", env, cleanup };
}

export function parseLocalProcessSandboxExtraPaths(value: unknown): LocalProcessSandboxPath[] {
  if (!Array.isArray(value)) return [];
  return value.map((entry, index) => {
    if (typeof entry === "string") {
      return { path: normalizeAbsolutePath(entry, `filesystemExtraPaths[${index}]`), access: "ro" };
    }
    if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
      throw new Error(`filesystemExtraPaths[${index}] must be an absolute path or { path, access } object.`);
    }
    const raw = entry as Record<string, unknown>;
    const access = raw.access === "rw" ? "rw" : raw.access === "ro" || raw.access == null ? "ro" : null;
    if (!access || typeof raw.path !== "string") {
      throw new Error(`filesystemExtraPaths[${index}] must use access "ro" or "rw" and an absolute path.`);
    }
    return { path: normalizeAbsolutePath(raw.path, `filesystemExtraPaths[${index}].path`), access };
  });
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Use exactly "ro" or "rw" for access (or omit it — undefined defaults to "ro").
  2. Ensure path is present and a string.
  3. Map legacy vocabulary at the config boundary: "readonly" -> "ro", "write" | "w" -> "rw".
  4. Reject any object whose access is not in [undefined, null, "ro", "rw"] before parsing so the failure surfaces earlier.

Example fix

// before
parseLocalProcessSandboxExtraPaths([
  { path: "/etc", access: "readonly" },
  { access: "ro" },
  { path: 123, access: "rw" },
]);

// after
parseLocalProcessSandboxExtraPaths([
  { path: "/etc", access: "ro" },
  { path: "/var/data", access: "ro" },
  { path: "/var/log", access: "rw" },
]);
Defensive patterns

Strategy: validation

Validate before calling

const ACCESS_ALIASES = { readonly: "ro", read: "ro", write: "rw", readwrite: "rw", w: "rw", r: "ro" } as Record<string, "ro" | "rw">;
function normalizeExtraPath(entry: { path: unknown; access?: unknown }): { path: string; access: "ro" | "rw" } {
  if (typeof entry.path !== "string" || entry.path.length === 0) throw new Error("extraPath.path must be a non-empty string");
  const rawAccess = typeof entry.access === "string" ? entry.access.toLowerCase() : undefined;
  const access: "ro" | "rw" | undefined = rawAccess === undefined ? "ro" : ACCESS_ALIASES[rawAccess] ?? (rawAccess === "ro" || rawAccess === "rw" ? rawAccess : undefined);
  if (!access) throw new Error(`Unsupported access: ${String(entry.access)}`);
  return { path: entry.path, access };
}

Type guard

function isExtraPathObject(value: unknown): value is { path: string; access?: 'ro' | 'rw' } {
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
  const raw = value as Record<string, unknown>;
  return typeof raw.path === "string" && (raw.access === undefined || raw.access === "ro" || raw.access === "rw");
}

Try / catch

try {
  const parsed = parseLocalProcessSandboxExtraPaths(config.filesystemExtraPaths);
} catch (error) {
  if (error instanceof Error && error.message.includes('must use access')) {
    throw new ConfigError(`filesystemExtraPaths access must be \"ro\" or \"rw\" (typo? legacy vocabulary?)`, { cause: error });
  }
  throw error;
}

Prevention

When it happens

Trigger: filesystemExtraPaths: [{ path: "/etc", access: "readonly" }] (wrong literal), [{ access: "ro" }] (path missing), [{ path: 123, access: "ro" }] (path not a string), or [{ path: "/etc", access: "write" }]. Each of these reaches the throw at local-process-sandbox.ts:504-506.

Common situations: Migration from another tool that uses "readonly"/"write", "r"/"w", or "read"/"write"; config typos; UI dropdowns that submit a label instead of the canonical value; or payload schemas that allow extra keys without validating the access vocabulary.

Related errors


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