can1357/oh-my-pi · error · Error
Rule "${rule.name}" has no usable TTSR condition. Add a `con
Error message
Rule "${rule.name}" has no usable TTSR condition. Add a `condition` (regex) or `astCondition` (ast-grep pattern) to its frontmatter. What it means
After loading an isolated rule markdown file, loadIsolatedRule registers it with TtsrManager. addRule returns false when the rule has no usable matching condition — i.e. its frontmatter defines neither a `condition` (regex) nor an `astCondition` (ast-grep pattern) — so nothing could ever trigger. The CLI throws this error telling you which frontmatter keys to add.
Source
Thrown at packages/coding-agent/src/cli/ttsr-cli.ts:324
const name = path.basename(resolved).replace(/\.(md|mdc)$/, "");
return buildRuleFromMarkdown(name, content, resolved, createSourceMeta("ttsr-cli", resolved, "project"), {
ruleName: name,
});
}
async function loadIsolatedRule(rulePath: string): Promise<{ rules: Rule[]; manager: TtsrManager }> {
const rule = await readIsolatedRule(rulePath);
const manager = await createTtsrManager({
enabled: true,
contextMode: "discard",
interruptMode: "always",
repeatMode: "once",
repeatGap: 10,
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);
View on GitHub (pinned to 9690622007)
Solutions
- Add a `condition` key with a regex to the rule's frontmatter.
- Or add an `astCondition` key with an ast-grep pattern for structural matching.
- Verify the condition compiles by re-running the command; also sanity-check regex syntax.
- Use `omp ttsr test` with a snippet that should match to confirm the new condition triggers.
Example fix
// before
---
name: no-secrets
description: Detect API keys
---
// after
---
name: no-secrets
description: Detect API keys
condition: "sk-[a-zA-Z0-9]{20,}"
--- Defensive patterns
Strategy: validation
Validate before calling
import * as fs from "node:fs";
const head = fs.readFileSync(rulePath, "utf8").split("---")[1] ?? "";
if (!/^condition:/m.test(head) && !/^astCondition:/m.test(head)) {
throw new Error(`${rulePath}: frontmatter needs ` + "`condition:` or `astCondition:`");
} Try / catch
try {
await runTest(args, json, cwd);
} catch (err) {
if (err instanceof Error && err.message.includes("no usable TTSR condition")) {
console.error(`${err.message}\nRule file: ${args.rule}`);
}
throw err;
} Prevention
- Start new rules from a template that includes condition or astCondition.
- Lint rule frontmatter in CI (require at least one condition key).
- Never commit rules with description-only frontmatter.
- Test each new rule with `omp ttsr test` and a matching snippet before committing.
When it happens
Trigger: Running `omp ttsr test --rule <file.md>` or `omp ttsr scan --rule <file.md>` where the markdown frontmatter lacks both `condition:` and `astCondition:` keys, or their values fail to compile into a usable rule.
Common situations: Authoring a new rule file that only has description/metadata frontmatter; copying a rule template without filling in the condition; a rule that was fine for documentation purposes but was never meant to match; malformed regex/AST pattern rejected during compile leaving no usable condition.
Related errors
- Model "${options.model}" not found
- No OAuth providers registered
- resolved.error (model resolution failure)
- No models available. Use --model to select a model or config
- Invalid alias "${aliasName}". Alias names must match ${ALIAS
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/917d49802ab333aa.
Report an issue: GitHub.