can1357/oh-my-pi · error

${targets.length} files matched; pass --in-place to rewrite

Error message

${targets.length} files matched; pass --in-place to rewrite them (--out takes a single file)

What it means

runCompressCommand allows multi-file compress runs only with --in-place: without in-place mode each file would need its own output, but --out accepts a single file. When resolution matched more than one file and --in-place was not passed, it throws with the match count and guidance.

Source

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

	}
	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 {
		console.error(`Compressing ${targets.length} file(s)${options.model ? ` with ${options.model}` : ""}`);
		progress.start(targets.length);
		const settled = await mapWithConcurrencyLimitAllSettled(
			targets,
			Math.min(concurrency, targets.length),
			async (target, index, signal) => {
				// A failing file must not cancel its peers, and must still be reported: turn
				// every failure into a result instead of letting it reject the batch entry.

View on GitHub (pinned to 9690622007)

Solutions

  1. Add --in-place to rewrite all matched files in place.
  2. Narrow the glob/file list to exactly one file and keep --out.
  3. Verify the match count in the message against your expectation (`ls` the glob) — an overly broad pattern is often the real bug.
  4. Loop in a script, invoking compress once per file with a distinct --out.

Example fix

// before
omp compress 'src/**/*.ts' --out out.ts   // 5 files matched
// after
omp compress 'src/**/*.ts' --in-place
Defensive patterns

Strategy: validation

Validate before calling

if (targets.length > 1 && !options.inPlace) {
  throw new Error(`${targets.length} files matched; pass --in-place to rewrite them (--out takes a single file)`);
}
// pre-check by scanning the same glob you plan to pass

Try / catch

try {
  await runCompressCommand({ files: [glob], inPlace: false });
} catch (err) {
  if (err instanceof Error && err.message.includes("pass --in-place to rewrite them")) {
    process.stderr.write(`${err.message}\n`);
  } else throw err;
}

Prevention

When it happens

Trigger: A glob (e.g. `src/**/*.ts`) matched 2+ files but --in-place was not supplied; or programmatically passing multiple files in options.files with inPlace unset.

Common situations: Glob broader than expected (matched more files than the user realized); scripted bulk compression forgetting --in-place; assuming --out could accept a directory for many outputs.

Related errors


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