can1357/oh-my-pi · error
No files to compress
Error message
No files to compress
What it means
After resolving targets, runCompressCommand throws if the resolved target list is empty. This happens when options.files is an empty array (or omitted with no positional file arguments), so there is nothing to compress. Unlike the per-pattern error, no input was given at all.
Source
Thrown at packages/coding-agent/src/compress/index.ts:88
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 {
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) => {View on GitHub (pinned to 9690622007)
Solutions
- Pass at least one file or glob: `omp compress src/foo.ts`.
- In scripts, guard before invoking: `[ ${#FILES[@]} -gt 0 ] || exit 1`.
- Check whether the shell pre-expanded a glob into nothing and adjust quoting ('*.ts' to defer expansion).
Example fix
// before FILES=$(git diff --name-only HEAD~1) omp compress $FILES // empty diff -> no args // after [ -n "$FILES" ] && omp compress $FILES || echo 'no changed files'
Defensive patterns
Strategy: validation
Validate before calling
if (!files || files.length === 0) {
throw new Error("compress requires at least one file or glob");
}
// check before calling runCompressCommand Type guard
function hasTargets(files: string[] | undefined): files is [string, ...string[]] {
return Array.isArray(files) && files.length > 0;
} Try / catch
try {
await runCompressCommand({ files });
} catch (err) {
if (err instanceof Error && err.message === "No files to compress") {
process.stderr.write(`${err.message} — pass file arguments\n`);
} else throw err;
} Prevention
- Always pass at least one file or glob to the compress command.
- In shell scripts, quote globs and check expansion (`${FILES:-}`) before invoking.
- In CI, skip the step when the changed-file list is empty instead of calling with [] .
- Assert non-empty args in wrappers around programmatic invocations.
When it happens
Trigger: Calling runCompressCommand({ files: [] }) programmatically, or the CLI wiring passing no positional file arguments to the compress command.
Common situations: Wrapper scripts where `$@` expanded to nothing (no files passed); CI jobs whose file list came from an empty diff/glob expansion; forgetting the positional file arguments entirely.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- unknown file type: {value}
- invalid size: {value}
- 2
- invalid --block-size argument '{0}'
- invalid --time-style argument {} Possible values are: - [p
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/170a0d2ccc6ea85a.
Report an issue: GitHub.