mihomo-party-org/clash-party · error

Unsupported ruleset behavior: ${behavior}

Error message

Unsupported ruleset behavior: ${behavior}

What it means

convertMrsRuleset converts .mrs binary rulesets using the mihomo core, but the behavior parameter comes from subscription-supplied rule-providers and is treated as untrusted input. Only 'domain', 'ipcidr', and 'classical' are accepted; any other value throws 'Unsupported ruleset behavior'.

Source

Thrown at src/main/config/profile.ts:697

  const { diffWorkDir = false } = await getAppConfig()
  const { current } = await getProfileConfig()
  if (isAbsolutePath(path)) {
    await atomicWriteFile(path, content, { encoding: 'utf8' })
  } else {
    await atomicWriteFile(
      join(diffWorkDir ? mihomoProfileWorkDir(current) : mihomoWorkDir(), path),
      content,
      { encoding: 'utf8' }
    )
  }
}

const MRS_RULESET_BEHAVIORS = ['domain', 'ipcidr', 'classical'] as const

export async function convertMrsRuleset(filePath: string, behavior: string): Promise<string> {
  // behavior 来自订阅下发的 rule-providers,属于不可信输入,只接受内核支持的固定取值
  if (!(MRS_RULESET_BEHAVIORS as readonly string[]).includes(behavior)) {
    throw new Error(`Unsupported ruleset behavior: ${behavior}`)
  }

  const { core = 'mihomo' } = await getAppConfig()
  const corePath = mihomoCorePath(core)
  const { diffWorkDir = false } = await getAppConfig()
  const { current } = await getProfileConfig()
  let fullPath: string
  if (isAbsolutePath(filePath)) {
    fullPath = filePath
  } else {
    fullPath = join(diffWorkDir ? mihomoProfileWorkDir(current) : mihomoWorkDir(), filePath)
  }

  const tempFileName = `mrs-convert-${randomBytes(8).toString('hex')}.txt`
  const tempFilePath = join(tmpdir(), tempFileName)

  try {
    // 使用 mihomo convert-ruleset 命令转换 MRS 文件为 text 格式

View on GitHub (pinned to 911e090537)

Solutions

  1. Set the rule-provider's behavior to exactly 'domain', 'ipcidr', or 'classical' (lowercase).
  2. Check the subscription's rule-providers config for typos or casing issues.
  3. If the subscription sends a bad value, override or fix that rule-provider entry locally.

Example fix

// before
rule-providers:
  ads:
    type: http
    behavior: domain-mrs
// after
rule-providers:
  ads:
    type: http
    behavior: domain
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = ['domain', 'ipcidr', 'classical'] as const
type Behavior = (typeof ALLOWED)[number]
function assertBehavior(b: string): asserts b is Behavior {
  if (!ALLOWED.includes(b as Behavior)) throw new Error(`bad behavior: ${b}`)
}
assertBehavior(behavior)
await convertMrsRuleset(filePath, behavior)

Type guard

function isMrsBehavior(v: string): v is 'domain' | 'ipcidr' | 'classical' {
  return ['domain', 'ipcidr', 'classical'].includes(v)
}

Try / catch

try {
  await convertMrsRuleset(filePath, behavior)
} catch (e) {
  if (e.message.startsWith('Unsupported ruleset behavior')) {
    // fix the rule-provider's behavior field in the config
  }
}

Prevention

When it happens

Trigger: Calling convertMrsRuleset(filePath, behavior) where behavior is not exactly one of 'domain' | 'ipcidr' | 'classical' — e.g. 'Domain', 'ip-cidr', 'final', or an arbitrary string from a remote rule-provider config.

Common situations: Subscription's rule-providers section uses a misspelled or non-mihomo behavior value; case mismatch (capitalized behavior from hand-edited config); malicious/odd subscription sending unexpected behavior values.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30). Data as JSON: /api/errors/d2d41fdd0ca5e779. Report an issue: GitHub.