ruvnet/ruflo · warning

Pattern rejected: exceeds maximum length of 500 characters

Error message

Pattern rejected: exceeds maximum length of 500 characters

What it means

addPattern() enforces a hard 500-character sanity bound on classification patterns, checked after the ReDoS heuristic. Even a safe regex of unbounded length is a compile-cost and review burden, so longer patterns are rejected outright with a fixed message. The limit is on the pattern string itself, not on matched input.

Source

Thrown at v3/@claude-flow/guidance/src/authority.ts:676

  }

  /**
   * Add a pattern to a classification.
   *
   * Validates the pattern against ReDoS heuristics before accepting it.
   * Rejects patterns with nested quantifiers (e.g., `(a+)+`) that can
   * cause catastrophic backtracking.
   *
   * @throws Error if the pattern is invalid regex or contains ReDoS-prone constructs
   */
  addPattern(classification: IrreversibilityClass, pattern: string): void {
    // ReDoS heuristic: reject nested quantifiers like (a+)+, (a*)+, (a+)*, etc.
    if (/([+*]|\{[0-9]+,?\})\s*\)[\s]*[+*]|\{[0-9]+,?\}/.test(pattern)) {
      throw new Error(`Pattern rejected: nested quantifiers detected (potential ReDoS): ${pattern}`);
    }
    // Also reject patterns longer than 500 chars as a sanity bound
    if (pattern.length > 500) {
      throw new Error(`Pattern rejected: exceeds maximum length of 500 characters`);
    }

    const regex = new RegExp(pattern, 'i');

    switch (classification) {
      case 'irreversible':
        this.irreversiblePatterns.push(regex);
        break;
      case 'costly-reversible':
        this.costlyReversiblePatterns.push(regex);
        break;
      case 'reversible':
        this.reversiblePatterns.push(regex);
        break;
    }
  }

  // ===== Private =====

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Split one long pattern into several addPattern() calls under the same classification
  2. Replace long literal alternations with a prefix or a shorter wildcard pattern
  3. Assert `pattern.length <= 500` in the code that generates patterns
  4. Store keyword lists as data and match with a Set instead of one mega-regex

Example fix

// before
authority.addPattern('irreversible', veryLongAlternation); // >500 chars, throws

// after
for (const chunk of chunkByLength(allLiterals, 400)) {
  authority.addPattern('irreversible', chunk);
}
Defensive patterns

Strategy: validation

Validate before calling

if (pattern.length > 500) {
  throw new Error('pattern exceeds the 500-char ledger limit');
}
authority.addPattern(classification, pattern);

Prevention

When it happens

Trigger: Generating a giant alternation of literals, e.g. `(path\\to\\a|path\\to\\b|... hundreds more)` that crosses 500 chars; concatenating many keywords into one pattern in a loop; LLM-generated patterns that enumerate exhaustive variants.

Common situations: Auto-building irreversible/costly-reversible pattern lists from filesystem inventories or log catalogs; keyword blacklists grown over time until they silently cross the cap.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/434c5e82850f61ed. Report an issue: GitHub.