{"record":{"id":"ec83b8d1123753a9","repo":"paperclipai/paperclip","slug":"deletion-requires-yes-ec83b8","errorCode":null,"errorMessage":"Deletion requires --yes.","messagePattern":"Deletion requires --yes\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"cli/src/commands/client/project.ts","lineNumber":197,"sourceCode":"          const updated = await ctx.api.patch<Project>(`${apiPath`/api/projects/${projectRef}`}${query}`, payload);\n          printOutput(updated, { json: ctx.json });\n        } catch (err) {\n          handleCommandError(err);\n        }\n      }),\n    { includeCompany: false },\n  );\n\n  addCommonClientOptions(\n    project\n      .command(\"delete\")\n      .description(\"Delete a project\")\n      .argument(\"<project>\", \"Project ID or shortname\")\n      .option(\"-C, --company-id <id>\", \"Company ID for shortname lookup\")\n      .option(\"--yes\", \"Confirm deletion\")\n      .action(async (projectRef: string, opts: ProjectDeleteOptions) => {\n        try {\n          if (!opts.yes) throw new Error(\"Deletion requires --yes.\");\n          const ctx = resolveCommandContext(opts);\n          const query = ctx.companyId ? `?${new URLSearchParams({ companyId: ctx.companyId }).toString()}` : \"\";\n          const deleted = await ctx.api.delete<Project>(`${apiPath`/api/projects/${projectRef}`}${query}`);\n          printOutput(deleted, { json: ctx.json });\n        } catch (err) {\n          handleCommandError(err);\n        }\n      }),\n    { includeCompany: false },\n  );\n}\n\nfunction parseCsv(value: string | undefined): string[] | undefined {\n  if (value === undefined) return undefined;\n  return value.split(\",\").map((part) => part.trim()).filter(Boolean);\n}\n\nfunction parseNullableString(value: string | undefined): string | null | undefined {","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/client/project.ts#L179-L215","documentation":"The `project delete` CLI command refuses to delete a project unless the `--yes` confirmation flag is present. The flag is declared as an optional Commander option (no default), so Commander itself does not enforce it; the action handler throws this error before any API call is made. The thrown error is caught by the surrounding try/catch and routed to handleCommandError, which prints it in red and exits the process with code 1.","triggerScenarios":"Running `paperclipai project delete <projectRef>` (or the namespaced subcommand path that registers this action) without appending `--yes`. Also produced by shell aliases, Makefile targets, or CI scripts that wrap the delete invocation but omit the flag.","commonSituations":"Automation/CI pipelines copied from a non-destructive command variant that dropped --yes; muscle memory from commands that prompt interactively (this one does not); aliases that strip unknown flags.","solutions":["Append `--yes` to the invocation: `paperclipai project delete <projectRef> --yes`","If resolving by shortname, also pass `-C <companyId>` together with `--yes`","In automation scripts, set the flag explicitly in the command array rather than expecting a prompt"],"exampleFix":"# before\npaperclipai project delete acme-website\n# after\npaperclipai project delete acme-website --yes","handlingStrategy":"validation","validationCode":"// Before invoking the delete action programmatically\nfunction assertDeleteConfirmed(opts: { yes?: boolean }): void {\n  if (!opts.yes) {\n    throw new Error(\"Refusing to delete without explicit --yes confirmation.\");\n  }\n}\nassertDeleteConfirmed(opts);","typeGuard":"function isDeleteConfirmed(opts: unknown): opts is { yes: true } {\n  return typeof opts === \"object\" && opts !== null && (opts as any).yes === true;\n}","tryCatchPattern":null,"preventionTips":["Always include --yes in delete scripts/aliases","Wrap destructive commands in a helper that injects --yes after its own confirmation prompt","Never assume the CLI will prompt interactively — these guards hard-stop"],"tags":["cli","destructive","validation","commander"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}