{"record":{"id":"b89b69208da03b10","repo":"can1357/oh-my-pi","slug":"targets-length-files-matched-pass-in-place-t","errorCode":null,"errorMessage":"${targets.length} files matched; pass --in-place to rewrite them (--out takes a single file)","messagePattern":"(.+?) files matched; pass --in-place to rewrite them \\(--out takes a single file\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/compress/index.ts","lineNumber":90,"sourceCode":"\t}\n\treturn [...found].sort();\n}\n\n/** Compress every requested file through the rewrite/approve loop. */\nexport async function runCompressCommand(options: CompressCommandOptions): Promise<CompressResult> {\n\tconst maxRounds = options.maxRounds ?? DEFAULT_MAX_ROUNDS;\n\tconst concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;\n\tif (!Number.isInteger(maxRounds) || maxRounds <= 0) throw new Error(\"--rounds must be a positive integer\");\n\tif (!Number.isInteger(concurrency) || concurrency <= 0) throw new Error(\"--agents must be a positive integer\");\n\tif (options.inPlace && options.output) throw new Error(\"--in-place and --out are mutually exclusive\");\n\t// Paths and patterns follow the shell's cwd, as a file-taking CLI must; the project\n\t// dir only scopes settings discovery for the sessions.\n\tconst invocationDir = process.cwd();\n\tconst cwd = getProjectDir();\n\tconst targets = await resolveCompressTargets(options.files, invocationDir);\n\tif (targets.length === 0) throw new Error(\"No files to compress\");\n\tif (targets.length > 1 && !options.inPlace) {\n\t\tthrow new Error(`${targets.length} files matched; pass --in-place to rewrite them (--out takes a single file)`);\n\t}\n\n\tconst abortController = new AbortController();\n\tconst abort = (): void => abortController.abort(new Error(\"Compress interrupted\"));\n\tprocess.once(\"SIGINT\", abort);\n\tprocess.once(\"SIGTERM\", abort);\n\tconst progress = createProgressReporter(\"Compressing\");\n\tconst emitToStdout = targets.length === 1 && !options.inPlace && options.output === undefined;\n\n\ttry {\n\t\tconsole.error(`Compressing ${targets.length} file(s)${options.model ? ` with ${options.model}` : \"\"}`);\n\t\tprogress.start(targets.length);\n\t\tconst settled = await mapWithConcurrencyLimitAllSettled(\n\t\t\ttargets,\n\t\t\tMath.min(concurrency, targets.length),\n\t\t\tasync (target, index, signal) => {\n\t\t\t\t// A failing file must not cancel its peers, and must still be reported: turn\n\t\t\t\t// every failure into a result instead of letting it reject the batch entry.","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/compress/index.ts#L72-L108","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add --in-place to rewrite all matched files in place.","Narrow the glob/file list to exactly one file and keep --out.","Verify the match count in the message against your expectation (`ls` the glob) — an overly broad pattern is often the real bug.","Loop in a script, invoking compress once per file with a distinct --out."],"exampleFix":"// before\nomp compress 'src/**/*.ts' --out out.ts   // 5 files matched\n// after\nomp compress 'src/**/*.ts' --in-place","handlingStrategy":"validation","validationCode":"if (targets.length > 1 && !options.inPlace) {\n  throw new Error(`${targets.length} files matched; pass --in-place to rewrite them (--out takes a single file)`);\n}\n// pre-check by scanning the same glob you plan to pass","typeGuard":null,"tryCatchPattern":"try {\n  await runCompressCommand({ files: [glob], inPlace: false });\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"pass --in-place to rewrite them\")) {\n    process.stderr.write(`${err.message}\\n`);\n  } else throw err;\n}","preventionTips":["Pair broad globs with --in-place by habit.","Preview glob expansion (`ls <glob> | wc -l`) so the match count is no surprise.","Use --out only when the file list is guaranteed to be a single file.","Loop per-file with individual --out paths when you need separate outputs."],"tags":["cli","argument-validation","glob","mutually-exclusive-options"],"backgroundTag":"multiple-targets-require-flag","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}