paperclipai/paperclip · error
ACPX provider package root must be an explicit normalized ab
Error message
ACPX provider package root must be an explicit normalized absolute path
What it means
createAcpxPackageJsonResolver validates its root parameter before resolving provider package.json files. The root must be a non-empty, absolute, null-byte-free, already-normalized path (resolve(root) === root). The library refuses relative paths, non-normalized paths containing '..' or '.', or paths with embedded NUL characters so downstream realpath/canonicalization logic cannot be tricked or fail ambiguously.
Source
Thrown at packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts:295
const providerExitProof = new WeakMap<ChildProcess, Promise<void>>();
export type AcpxPackageJsonResolver = (
packageName: string,
issuerPackageJsonPath?: string,
) => string;
export function createAcpxPackageJsonResolver(
providerPackageRoot: string | undefined,
providerPackageManifest?: string,
): AcpxPackageJsonResolver {
const root = providerPackageRoot?.trim();
if (
!root ||
!isAbsolute(root) ||
root.includes("\0") ||
resolve(root) !== root
) {
throw new Error(
"ACPX provider package root must be an explicit normalized absolute path",
);
}
const manifest = (
providerPackageManifest ?? resolve(root, "package.json")
).trim();
if (
!manifest ||
!isAbsolute(manifest) ||
manifest.includes("\0") ||
resolve(manifest) !== manifest
) {
throw new Error(
"ACPX provider package manifest must be an explicit normalized absolute path",
);
}
const canonicalRoot = realpathSync(root);
const canonicalManifest = realpathSync(manifest);View on GitHub (pinned to 01ad858492)
Solutions
- Wrap the configured root with path.resolve(path.normalize(root)) before calling the resolver
- Expand '~' and environment variables in the config value before use
- Reject empty config values upstream with a clear 'provider root not configured' message instead of letting the resolver throw
- Verify with isAbsolute(root) && resolve(root) === root in your own code and log the offending value
Example fix
// before
const resolver = createAcpxPackageJsonResolver(cfg.providerRoot);
// after
const root = path.resolve(expandTilde(cfg.providerRoot));
if (!path.isAbsolute(root) || path.resolve(root) !== root) throw new Error('providerRoot must be a normalized absolute path');
const resolver = createAcpxPackageJsonResolver(root); Defensive patterns
Strategy: validation
Validate before calling
import path from 'node:path';
function assertValidRoot(root: string | undefined): asserts root is string {
if (!root || !path.isAbsolute(root) || root.includes('\0') || path.resolve(root) !== root) {
throw new Error(`providerRoot must be a normalized absolute path, got: ${JSON.stringify(root)}`);
}
} Type guard
function isNormalizedAbsolutePath(p: unknown): p is string {
return typeof p === 'string' && p.length > 0 && path.isAbsolute(p) && !p.includes('\0') && path.resolve(p) === p;
} Try / catch
try {
const resolver = createAcpxPackageJsonResolver(cfg.providerRoot);
} catch (err) {
if (err instanceof Error && /explicit normalized absolute path/.test(err.message)) {
throw new Error(`Invalid providerRoot in config: ${JSON.stringify(cfg.providerRoot)} — use path.resolve()`);
}
throw err;
} Prevention
- Always run configured paths through path.resolve() at config-load time, not at use time
- Expand '~' and env vars before validation
- Store absolute paths in config files rather than relative ones
- Add a config-schema check (e.g. zod refine()) mirroring the resolver's path invariants
When it happens
Trigger: Calling the resolver (directly or via defaultPackageJsonResolver) with root = '' , a relative path like './node/pkg', a non-normalized path like '/opt/acpx/../acpx/provider' where resolve(root) !== root, or a path containing '\0'.
Common situations: Config value for the provider package root read from an env var or settings file that was never path.resolve()'d; test code passing fixture-relative paths; a user config like '~/.acpx/provider' with an unexpanded tilde (not absolute).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ACPX provider package manifest must be an explicit normalize
- ACPX provider package manifest resolves outside the selected
- ACPX provider node_modules resolves outside the selected pro
- Select Codex to use the native Codex runner.
- OpenCode evals require exact version 1.18.17; received ${ver
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/d96db63282b202bf.
Report an issue: GitHub.