can1357/oh-my-pi · error
Unknown rule: ${ruleName} Available: ${availableStr}
Error message
Unknown rule: ${ruleName}
Available: ${availableStr} What it means
The rule:// protocol handler resolves internal URLs of the form rule://<name> to the markdown content of an active capability rule. Before resolving, it looks up the rule name in the list returned by getActiveRules(); if no rule with that exact name is registered, it throws this error listing all currently available rule names (or "none" if no rules are active). It is a lookup-failure error meaning the referenced rule does not exist or is not active in the current session.
Source
Thrown at packages/coding-agent/src/internal-urls/rule-protocol.ts:26
import type { InternalResource, InternalUrl, ProtocolHandler, UrlCompletion } from "./types";
export class RuleProtocolHandler implements ProtocolHandler {
readonly scheme = "rule";
readonly immutable = true;
async resolve(url: InternalUrl): Promise<InternalResource> {
const rules = getActiveRules();
const ruleName = url.rawHost || url.hostname;
if (!ruleName) {
throw new Error("rule:// URL requires a rule name: rule://<name>");
}
const rule = rules.find(r => r.name === ruleName);
if (!rule) {
const available = rules.map(r => r.name);
const availableStr = available.length > 0 ? available.join(", ") : "none";
throw new Error(`Unknown rule: ${ruleName}\nAvailable: ${availableStr}`);
}
return {
url: url.href,
content: rule.content,
contentType: "text/markdown",
size: Buffer.byteLength(rule.content, "utf-8"),
sourcePath: rule.path,
notes: [],
};
}
async complete(): Promise<UrlCompletion[]> {
return getActiveRules().map(rule => ({
value: rule.name,
...(rule.description ? { description: rule.description } : {}),
}));
}View on GitHub (pinned to 9690622007)
Solutions
- Read the 'Available:' line in the error message and use one of the listed rule names exactly (they are case- and separator-sensitive).
- Call getActiveRules() (or the rule:// completion endpoint) in your session to enumerate valid rule names and verify the one you reference exists.
- If the rule should exist, check that it is defined in a location that is actually loaded/active (correct project directory, rules enabled in settings) before resolving the URL.
- If the rule was renamed or deleted, update all prompt/config references to the new rule://<name> URL.
Example fix
// before
await resolveUrl(new URL("rule://code-style"));
// after (verify the exact active rule name first)
const names = getActiveRules().map(r => r.name); // e.g. ["code_style"]
if (names.includes("code_style")) {
await resolveUrl(new URL("rule://code_style"));
} Defensive patterns
Strategy: validation
Validate before calling
import { getActiveRules } from "../capability/rule";
function canResolveRule(name: string): boolean {
return getActiveRules().some(r => r.name === name);
}
const ruleName = url.hostname;
if (!canResolveRule(ruleName)) {
const available = getActiveRules().map(r => r.name);
throw new Error(`Rule "${ruleName}" not active. Available: ${available.join(", ") || "none"}`);
} Type guard
function findActiveRule(name: string): Rule | null {
return getActiveRules().find(r => r.name === name) ?? null;
}
// use: const rule = findActiveRule(name); if (rule === null) { /* handle */ } Try / catch
try {
const resource = await ruleHandler.resolve(url);
return resource;
} catch (err) {
if (err instanceof Error && err.message.startsWith("Unknown rule:")) {
const available = err.message.split("Available:")[1]?.trim() ?? "none";
return fallbackResource(`Rule not found. Active rules: ${available}`);
}
throw err;
} Prevention
- Generate rule:// URLs from the completion API or getActiveRules() instead of hardcoding names.
- Treat rule names as case- and separator-sensitive identifiers; copy them verbatim.
- After any rules rename/refactor, grep prompts and configs for rule:// references.
- Resolve rule URLs only after rules are loaded for the active project directory.
When it happens
Trigger: Calling RuleProtocolHandler.resolve(new URL('rule://some-name')) (or resolving a rule:// internal URL through the URL registry) where 'some-name' does not exactly match the name of any rule returned by getActiveRules(): a typo in the rule name, a rule that was renamed or removed, a rule defined in a directory not loaded as active, or referencing a rule:// URL before rules are registered.
Common situations: Hand-written agent prompts or configs referencing rule:// URLs with stale names after a rules refactor; case or hyphen/underscore mismatches between the URL host and the rule name; rules loaded from a different working directory than the one active at resolve time; relying on a rule that only exists when certain capabilities/directories are enabled.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Failed to load tree-sitter language: {err}
- sso-token-missing
- sso-token-expired
- Destination option ${key} must be a string
- Destination option ${key} must be a finite number
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/77623b49d93affdc.
Report an issue: GitHub.