can1357/oh-my-pi · error · Error
Invalid --source: ${args.source}. Expected one of: ${TTSR_SO
Error message
Invalid --source: ${args.source}. Expected one of: ${TTSR_SOURCES.join(", ")} What it means
`omp ttsr test` accepts `--source` to set the match context origin, which must be one of the enumerated TTSR_SOURCES values: text, thinking, or tool. runTest validates the raw string before use; anything else throws this error listing the allowed values. This is an argument-validation guard so an invalid source never silently alters rule scoping.
Source
Thrown at packages/coding-agent/src/cli/ttsr-cli.ts:338
builtinRules: true,
disabledRules: [],
});
if (!manager.addRule(rule)) {
throw new Error(
`Rule "${rule.name}" has no usable TTSR condition. Add a \`condition\` (regex) or \`astCondition\` (ast-grep pattern) to its frontmatter.`,
);
}
return { rules: manager.getRules(), manager };
}
async function loadIsolatedScanRule(rulePath: string): Promise<Rule[]> {
const rule = await readIsolatedRule(rulePath);
return filterTtsrRulesForScan([rule]);
}
async function runTest(args: TtsrTestArgs, json: boolean, cwd: string): Promise<void> {
if (args.source && !TTSR_SOURCES.includes(args.source)) {
throw new Error(`Invalid --source: ${args.source}. Expected one of: ${TTSR_SOURCES.join(", ")}`);
}
const snippet = await readSnippet(args);
// Infer match context: when the user points --file at a source file and
// doesn't pick a source, default to tool/edit with that path so tool-scoped
// rules (the common case, e.g. tool:edit(*.ts)) match like they would live.
const filePath = args.filePath ?? (args.file && args.file !== STDIN_MARKER ? path.resolve(args.file) : undefined);
const source: TtsrMatchSource =
args.source ?? (filePath && SOURCE_FILE_EXT.test(path.extname(filePath)) ? "tool" : "text");
const tool = args.tool ?? (source === "tool" ? "edit" : undefined);
// A supplied source file whose extension is unknown falls through to the
// text (prose) context, where tool-scoped rules can never match. Surface
// that so a false negative reads as a context mismatch, not a bad regex.
const inferenceNote =
!args.source && filePath && source === "text"
? `inferred --source text from '${path.extname(filePath) || filePath}' (not in the source-file extension set); pass --source tool --tool edit to evaluate tool-scoped rules`View on GitHub (pinned to 9690622007)
Solutions
- Use one of: `--source text`, `--source thinking`, or `--source tool`.
- If you meant to name a tool like edit/write, pass it via `--tool` together with `--source tool`.
- Mind case sensitivity — values are lowercase.
- Omit --source entirely to let the CLI infer it from --file (tool for source files, text otherwise).
Example fix
// before omp ttsr test --snippet "..." --source edit --tool edit // after omp ttsr test --snippet "..." --source tool --tool edit
Defensive patterns
Strategy: validation
Validate before calling
const SOURCES = ["text", "thinking", "tool"] as const;
if (args.source && !SOURCES.includes(args.source)) {
throw new Error(`--source must be one of ${SOURCES.join("|")}`);
} Type guard
function isTtsrSource(v: string): v is TtsrMatchSource {
return (TTSR_SOURCES as readonly string[]).includes(v);
} Try / catch
try {
await runTtsrCommand(args);
} catch (err) {
if (err instanceof Error && err.message.startsWith("Invalid --source:")) {
console.error(`${err.message} (values are lowercase)`);
process.exitCode = 2;
} else throw err;
} Prevention
- Remember the valid set: text | thinking | tool (lowercase, case-sensitive).
- Use --tool for tool names like edit/write; --source only takes the three enum values.
- Omit --source to let the CLI infer from --file.
- Add shell completion or a wrapper script that validates the value.
When it happens
Trigger: Running `omp ttsr test ... --source <value>` where value is not exactly `text`, `thinking`, or `tool` — typos like `tools`, `Text` (case-sensitive), `editor`, or passing a tool name to --source instead of --tool.
Common situations: Confusing --source with --tool (e.g. `--source edit` instead of `--tool edit`); autocomplete/history from a different command's flag values; shell variable interpolation injecting an unexpected value.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid value: ${rawValue}. Valid values: ${valid.join(", ")
- Unknown disposition: ${status}
- Expected --${name} to be one of: ${[...desc.options].join(",
- Expected ${argName} to be one of: ${[...desc.options].join("
- Unsupported language '{value}'. Supported: {}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1ab38f9260197b91.
Report an issue: GitHub.