paperclipai/paperclip · error · Error
Applying a company import from a non-interactive terminal re
Error message
Applying a company import from a non-interactive terminal requires --yes. Use --dry-run first to inspect the preview.
What it means
Thrown by resolveCompanyImportApplyConfirmationMode when an apply is run from a non-interactive terminal (no TTY on stdin/stdout) without --yes. Without a TTY the confirmation prompt cannot be displayed, so the library blocks the destructive apply and points the caller at --dry-run.
Source
Thrown at cli/src/commands/client/company.ts:814
url.hash = "";
return url.toString();
}
export function resolveCompanyImportApplyConfirmationMode(input: {
yes?: boolean;
interactive: boolean;
json: boolean;
}): "skip" | "prompt" {
if (input.yes) {
return "skip";
}
if (input.json) {
throw new Error(
"Applying a company import with --json requires --yes. Use --dry-run first to inspect the preview.",
);
}
if (!input.interactive) {
throw new Error(
"Applying a company import from a non-interactive terminal requires --yes. Use --dry-run first to inspect the preview.",
);
}
return "prompt";
}
export function isHttpUrl(input: string): boolean {
return /^https?:\/\//i.test(input.trim());
}
export function looksLikeRepoUrl(input: string): boolean {
try {
const url = new URL(input.trim());
if (url.protocol !== "https:") return false;
const segments = url.pathname.split("/").filter(Boolean);
return segments.length >= 2;
} catch {
return false;View on GitHub (pinned to 67001ec6eb)
Solutions
- Add --yes to the apply command when running non-interactively.
- Allocate a TTY if you genuinely want the prompt (ssh -t, docker run -t -i, or run directly in a terminal).
- Run --dry-run first in the same environment to validate the package, then apply with --yes.
- In code, detect !process.stdin.isTTY up front and force yes:true before calling resolveCompanyImportApplyConfirmationMode.
Example fix
# before (cron) 0 2 * * * paperclipai company import pkg.zip --target new-company # after 0 2 * * * paperclipai company import pkg.zip --target new-company --yes
Defensive patterns
Strategy: validation
Validate before calling
function resolveConfirmationMode(input: { yes?: boolean; interactive: boolean; json: boolean }) {
const nonInteractive = !input.interactive;
if (nonInteractive && !input.yes) {
throw new Error("Non-interactive terminal: pass --yes or run interactively.");
}
return input.yes ? "skip" : "prompt";
} Type guard
function isInteractiveApplyReady(input: { yes?: boolean; interactive: boolean }): boolean {
return input.yes === true || input.interactive === true;
} Prevention
- Detect TTY up front and fail fast with a clear message.
- Bake --yes into every scheduled/CI invocation.
- Document that cron/docker/ssh-default sessions are non-interactive.
When it happens
Trigger: Piping stdout into a file or another command, running inside cron/systemd/Docker without a pseudo-TTY, SSH non-interactive sessions, or any shell where process.stdin.isTTY or process.stdout.isTTY is false — and --yes is not set.
Common situations: Scheduled nightly imports, CI runners, containerized jobs, 'nohup' or backgrounded processes, and redirected output (>'log'). The interactive prompt worked locally but fails in the scheduled environment.
Related errors
- Applying a company import with --json requires --yes. Use --
- Export output directory ${root} already contains files. Re-r
- Existing-company imports require a companyId to resolve the
- GitHub source must be a GitHub or GitHub Enterprise URL, or
- Invalid GitHub URL.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/ca7ad461dbf8a769.
Report an issue: GitHub.