can1357/oh-my-pi · error
No files matched "${pattern}"
Error message
No files matched "${pattern}" What it means
resolveCompressTargets maps user-supplied file arguments to concrete files. Arguments containing glob metacharacters are scanned with Bun.Glob; if a pattern matches zero files it throws rather than silently compressing nothing. This catches typos and stale patterns early.
Source
Thrown at packages/coding-agent/src/compress/index.ts:65
* Expand `patterns` into a deduplicated, sorted list of absolute file paths.
*
* Entries containing glob metacharacters are matched against `cwd`; everything else is
* treated as a literal path so filenames containing brackets still resolve. Throws when
* a literal path is missing or a pattern matches nothing, since silently compressing
* fewer files than asked is worse than failing.
*/
export async function resolveCompressTargets(patterns: readonly string[], cwd: string): Promise<string[]> {
const found = new Set<string>();
for (const pattern of patterns) {
if (/[*?[\]{}]/.test(pattern)) {
// `dot: true` — prompt corpora live under dot directories such as `.omp/commands`.
const matches = new Bun.Glob(pattern).scanSync({ cwd, absolute: true, onlyFiles: true, dot: true });
let matched = 0;
for (const match of matches) {
found.add(match);
matched += 1;
}
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 projectView on GitHub (pinned to 9690622007)
Solutions
- Run `ls` with the same pattern from your current directory to see what it expands to; fix the pattern.
- cd to the directory containing the target files before running the command (patterns resolve against the shell cwd).
- Use a direct file path instead of a glob when you know the exact file.
- Check file extension/case sensitivity (especially on Linux).
Example fix
// before omp compress 'src/utils/*.ts' // No files matched ls src/utils // dir actually named src/lib // after omp compress 'src/lib/*.ts'
Defensive patterns
Strategy: validation
Validate before calling
import { globSync } from "node:fs";
function patternHasMatches(pattern: string, cwd: string): boolean {
try { return new Bun.Glob(pattern).scanSync({ cwd, onlyFiles: true, dot: true }).size > 0; }
catch { return false; }
}
// call before invoking compress with a glob Try / catch
try {
await runCompressCommand({ files: [pattern] });
} catch (err) {
if (err instanceof Error && err.message.startsWith('No files matched')) {
process.stderr.write(`${err.message} — check cwd and pattern\n`);
} else throw err;
} Prevention
- Test globs with `ls <pattern>` in the same directory before running compress.
- Remember patterns resolve against the shell's cwd, not the project dir.
- Watch extension and case sensitivity on Linux (ts vs TS, md vs MD).
- Use forward slashes in globs even on Windows.
When it happens
Trigger: Running the compress command with a glob pattern (contains *, ?, [, etc.) that matches no files under cwd — e.g. `src/**/*.ts` in a repo with no src dir, wrong extension, or pattern relative to the wrong directory (cwd is the shell's invocation dir, not the project dir).
Common situations: Typo in path or extension (*.tsx vs *.ts); running from a different directory than expected; case-sensitive filesystem mismatch (Readme.MD vs readme.md); files excluded by `dot`/symlink expectations; globbing on Windows paths with backslashes.
Related errors
- Import source is neither file nor directory: ${target}
- Not a file: ${shortenPath(resolved)}
- Invalid selection: ${choice}
- Session file not found: ${resolved}
- ${targets.length} files matched; pass --in-place to rewrite
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/489eba7c1ce5dad0.
Report an issue: GitHub.