can1357/oh-my-pi · error

--in-place and --out are mutually exclusive

Error message

--in-place and --out are mutually exclusive

What it means

runCompressCommand supports either in-place rewriting of the input files or writing a single compressed file via --out. Supplying both flags is ambiguous (where should results go for each target?), so it throws immediately. This is a pure option-conflict guard, checked before any file resolution.

Source

Thrown at packages/coding-agent/src/compress/index.ts:82

			}
			if (matched === 0) throw new Error(`No files matched "${pattern}"`);
			continue;
		}
		const resolved = path.resolve(cwd, pattern);
		const stat = await fs.stat(resolved).catch(() => undefined);
		if (!stat?.isFile()) throw new Error(`Not a file: ${shortenPath(resolved)}`);
		found.add(resolved);
	}
	return [...found].sort();
}

/** Compress every requested file through the rewrite/approve loop. */
export async function runCompressCommand(options: CompressCommandOptions): Promise<CompressResult> {
	const maxRounds = options.maxRounds ?? DEFAULT_MAX_ROUNDS;
	const concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
	if (!Number.isInteger(maxRounds) || maxRounds <= 0) throw new Error("--rounds must be a positive integer");
	if (!Number.isInteger(concurrency) || concurrency <= 0) throw new Error("--agents must be a positive integer");
	if (options.inPlace && options.output) throw new Error("--in-place and --out are mutually exclusive");
	// Paths and patterns follow the shell's cwd, as a file-taking CLI must; the project
	// dir only scopes settings discovery for the sessions.
	const invocationDir = process.cwd();
	const cwd = getProjectDir();
	const targets = await resolveCompressTargets(options.files, invocationDir);
	if (targets.length === 0) throw new Error("No files to compress");
	if (targets.length > 1 && !options.inPlace) {
		throw new Error(`${targets.length} files matched; pass --in-place to rewrite them (--out takes a single file)`);
	}

	const abortController = new AbortController();
	const abort = (): void => abortController.abort(new Error("Compress interrupted"));
	process.once("SIGINT", abort);
	process.once("SIGTERM", abort);
	const progress = createProgressReporter("Compressing");
	const emitToStdout = targets.length === 1 && !options.inPlace && options.output === undefined;

	try {

View on GitHub (pinned to 9690622007)

Solutions

  1. Pick one mode: use `--in-place` alone to rewrite input files, or `--out <file>` alone to write a single result.
  2. Remove the conflicting flag from your wrapper script/alias.
  3. Run two separate invocations if you need both a rewritten file and an output copy.

Example fix

// before
omp compress file.ts --in-place --out result.ts
// after
omp compress file.ts --out result.ts
Defensive patterns

Strategy: validation

Validate before calling

if (options.inPlace && options.output) {
  throw new Error("--in-place and --out are mutually exclusive");
}
// check before invoking runCompressCommand

Try / catch

try {
  await runCompressCommand(options);
} catch (err) {
  if (err instanceof Error && err.message === "--in-place and --out are mutually exclusive") {
    process.stderr.write(`${err.message} — choose one output mode\n`);
  } else throw err;
}

Prevention

When it happens

Trigger: Invoking compress with both `--in-place` and `--out <path>` (or setting both options.inPlace and options.output programmatically).

Common situations: Aliases or wrapper scripts that always append --in-place while the user also passes --out; copy-pasted command lines combining examples; config-driven invocations where both flags were enabled.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/72076b8eaf416080. Report an issue: GitHub.