paperclipai/paperclip · error · Error
Cannot build API path with an empty path segment.
Error message
Cannot build API path with an empty path segment.
What it means
Thrown by the apiPath tagged template in common.ts when any interpolated segment is null, undefined, or trims to an empty string. apiPath is the path builder used across CLI commands (e.g. apiPath`/api/agents/${agentRef}`), and it URL-encodes each segment; an empty segment would produce a doubled slash / ambiguous route, so it fails fast instead.
Source
Thrown at cli/src/commands/client/common.ts:128
export function resolveApiBase(options: Pick<BaseClientOptions, "apiBase" | "config">, profile: ClientContextProfile = {}): string {
return normalizeApiBase(
options.apiBase?.trim() ||
process.env.PAPERCLIP_API_URL?.trim() ||
profile.apiBase ||
inferApiBaseFromConfig(options.config),
);
}
export function normalizeApiBase(apiBase: string): string {
return apiBase.trim().replace(/\/+$/, "");
}
export function apiPath(strings: TemplateStringsArray, ...values: Array<string | number | boolean | null | undefined>): string {
let path = strings[0] ?? "";
values.forEach((value, index) => {
if (value === null || value === undefined || String(value).trim() === "") {
throw new Error("Cannot build API path with an empty path segment.");
}
path += `${encodeURIComponent(String(value))}${strings[index + 1] ?? ""}`;
});
return path;
}
export function inferContentTypeFromPath(filePath: string): string | undefined {
const ext = filePath.split(/[\\/]/).pop()?.split(".").pop()?.toLowerCase();
if (!ext) return undefined;
// These MIME strings are matched against the server's issue-attachment
// allowlist (server/src/attachment-types.ts DEFAULT_ALLOWED_TYPES) by EXACT
// string, so text types must carry no "; charset=..." parameter or the upload
// is rejected with "422 Unsupported attachment content type". Keep this set in
// sync with that allowlist (plus svg/avif, accepted by the asset routes).
return {
avif: "image/avif",
csv: "text/csv",
gif: "image/gif",View on GitHub (pinned to 67001ec6eb)
Solutions
- Validate the id is a non-empty string before calling the API: `if (!id) throw new Error('id required')`.
- For company-scoped calls, ensure --company-id / PAPERCLIP_COMPANY_ID / profile companyId is set (see [17]).
- Guard upstream: resolveCommandContext with requireCompany:true catches missing company earlier.
- If the id is legitimately optional, branch the path construction rather than interpolating undefined.
Example fix
// before
await api.get(apiPath`/api/agents/${agentId}`); // agentId undefined
// after
if (!agentId) throw new Error("agentId is required");
await api.get(apiPath`/api/agents/${agentId}`); Defensive patterns
Strategy: validation
Validate before calling
function buildPath(segments: Array<string | number | undefined>): string {
const parts = segments.map((s) => {
if (s === null || s === undefined || String(s).trim() === '') {
throw new Error(`Empty path segment in ${JSON.stringify(segments)}`);
}
return encodeURIComponent(String(s));
});
return parts.join('/');
} Type guard
function isNonEmptyId(v: unknown): v is string {
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try { apiPath`/api/agents/${agentId}`; }
catch (err) {
const msg = err instanceof Error ? err.message : '';
if (msg === 'Cannot build API path with an empty path segment.') {
console.error('Tried to build a path with a missing id. Validate inputs before formatting.');
process.exit(2);
}
throw err;
} Prevention
- Validate every id is a non-empty string BEFORE interpolating into apiPath.
- For company-scoped paths, ensure companyId is resolved first (see [17]).
- Prefer resolveCommandContext({ requireCompany: true }) to fail earlier and more clearly.
- Never pass optional fields directly into the template; branch when they are absent.
When it happens
Trigger: Passing an undefined variable into an apiPath interpolation: e.g. apiPath`/api/agents/${agentId}` when agentId is undefined, apiPath`/api/companies/${companyId}/...` when companyId is empty, or a numeric 0/empty boolean. Any caller that did not validate its id before formatting the path.
Common situations: A command path computed ids from user input/env and skipped validation. A slug resolver returned undefined. A company-scoped call where companyId was never resolved (closely related to [17], but this fires later, at path-build time).
Related errors
- --file is required
- Challenge secret is required. Pass --token or --token-env.
- Invalid --include value. Use one or more of: company,agents,
- Skill reference is required unless --all is used.
- Refusing to delete without --yes
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/b65bd5de2b81191e.
Report an issue: GitHub.