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

  1. Validate the id is a non-empty string before calling the API: `if (!id) throw new Error('id required')`.
  2. For company-scoped calls, ensure --company-id / PAPERCLIP_COMPANY_ID / profile companyId is set (see [17]).
  3. Guard upstream: resolveCommandContext with requireCompany:true catches missing company earlier.
  4. 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

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


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