paperclipai/paperclip · error
networkAllowlist[${index}] must be a string.
Error message
networkAllowlist[${index}] must be a string. What it means
Thrown by parseLocalProcessNetworkAllowlist while iterating the networkAllowlist option. Each entry is required to be a string before it is forwarded to parseNetworkAllowlistEntry for hostname/port parsing. The check exists because the array is consumed from untyped config (the value parameter is typed unknown) and silently coercing non-strings would mask genuine misconfiguration.
Source
Thrown at packages/adapter-utils/src/local-process-sandbox.ts:145
const parsed = new URL(trimmed.includes("://") ? trimmed : `https://${trimmed}`);
if (parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
throw new Error("path");
}
hostname = parsed.hostname.toLowerCase();
port = parsed.port || null;
} catch {
throw new Error(`networkAllowlist[${index}] must be a hostname, hostname:port, or origin URL.`);
}
if (!hostname || hostname === "*" || hostname.startsWith("*.")) {
throw new Error(`networkAllowlist[${index}] must use an exact hostname; wildcards are not supported.`);
}
return { hostname, port };
}
export function parseLocalProcessNetworkAllowlist(value: unknown): string[] {
if (!Array.isArray(value)) return [];
return value.map((entry, index) => {
if (typeof entry !== "string") throw new Error(`networkAllowlist[${index}] must be a string.`);
const rule = parseNetworkAllowlistEntry(entry, index);
return rule.port ? `${rule.hostname}:${rule.port}` : rule.hostname;
});
}
export function parseLocalProcessNetworkScope(value: unknown): LocalProcessNetworkScope | null {
if (value == null || value === "") return null;
if (value === "deny" || value === "allowlist") return value;
throw new Error('networkScope must be "deny" or "allowlist".');
}
export function parseLocalProcessFilesystemScope(value: unknown): "workspace" | null {
if (value == null || value === "") return null;
if (value === "workspace") return value;
throw new Error('filesystemScope must be "workspace".');
}
function isNetworkTargetAllowed(hostname: string, port: string, rules: NetworkAllowlistRule[]): boolean {View on GitHub (pinned to 67001ec6eb)
Solutions
- Inspect the failing index in the message (networkAllowlist[i]) and confirm that element is a string in the source config.
- Quote every entry: pass ["example.com", "example.com:443", "https://example.com"] rather than mixed types.
- If the array is sourced from user input, coerce or reject before calling parseLocalProcessNetworkAllowlist: entries.filter((e): e is string => typeof e === "string").
- Validate the array shape with a zod/JSON-schema validator on the config boundary so the failure surfaces at load time, not at sandbox spawn.
Example fix
// before const allowlist = [443, "api.example.com"]; const parsed = parseLocalProcessNetworkAllowlist(allowlist); // after const allowlist = ["example.com:443", "api.example.com"]; const parsed = parseLocalProcessNetworkAllowlist(allowlist);
Defensive patterns
Strategy: validation
Validate before calling
function isValidAllowlist(value: unknown): value is string[] {
return Array.isArray(value) && value.every((e) => typeof e === "string");
}
if (!isValidAllowlist(config.networkAllowlist)) {
throw new Error("networkAllowlist must be an array of strings");
}
const parsed = parseLocalProcessNetworkAllowlist(config.networkAllowlist); Type guard
function isNetworkAllowlistEntry(value: unknown): value is string {
return typeof value === "string";
}
function assertNetworkAllowlist(value: unknown): asserts value is string[] {
if (!Array.isArray(value) || !value.every(isNetworkAllowlistEntry)) {
throw new Error("networkAllowlist must be string[]");
}
} Try / catch
try {
const parsed = parseLocalProcessNetworkAllowlist(config.networkAllowlist);
} catch (error) {
if (error instanceof Error && error.message.startsWith("networkAllowlist[")) {
throw new ConfigError(`Invalid network allowlist config: ${error.message}`, { cause: error });
}
throw error;
} Prevention
- Type the config field as string[] at the boundary, not (string | number)[].
- Validate with a schema (zod, JSON-schema) at config load so this surfaces before sandbox spawn.
- Add a unit test that round-trips mixed-type arrays through your validator.
When it happens
Trigger: Calling parseLocalProcessNetworkAllowlist with an array containing a non-string element, e.g. a number (443), boolean, null, nested array, or plain object. The map callback hits the typeof guard at local-process-sandbox.ts:145 and throws before any URL parsing runs.
Common situations: YAML/JSON config loaded with numeric ports (networkAllowlist: [443, "example.com"]), a copy/paste that drops quotes around a hostname, or a default-export that returns an object literal instead of a string array. Also hit when adapter config is forwarded verbatim from an upstream API payload that types the field as (string | number)[].
Related errors
- networkScope must be "deny" or "allowlist".
- networkScope="allowlist" requires at least one valid network
- filesystemExtraPaths[${index}] must be an absolute path or {
- filesystemExtraPaths[${index}] must use access "ro" or "rw"
- networkAllowlist[${index}] must not be empty.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/7d4c08948b576abb.
Report an issue: GitHub.