Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Apply safe error-pattern matching rules for agentic engines.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 43% | 0% |
| case-10 | ✗→✓ | ▲ Improved | -39% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 57% | 0% |
| case-17 | ✗→✓ | ▲ Improved | -33% | 0% |
| case-18 | ✗→✓ | ▲ Improved | 166% | 0% |
Use these regex safety rules in agentic engines to prevent JavaScript infinite loops.
With the JavaScript global flag (/pattern/g), zero-width matches can cause infinite loops because:
regex.exec() with the g flag uses lastIndex to track positionlastIndex doesn't advance❌ NEVER USE THESE PATTERNS:
javascript// Pure .* - matches everything including empty string at end /.*/g // Single character with * - matches zero or more (including zero) /a*/g // Patterns that can match empty string /(x|y)*/g
✅ ALWAYS USE PATTERNS LIKE THESE:
javascript// Required prefix before .* /error.*/gi /error.*permission.*denied/gi // Specific structure with required content /\[(\d{4}-\d{2}-\d{2})\]\s+(ERROR):\s+(.+)/g // Required characters throughout /access denied.*user.*not authorized/gi
.+ instead of .* when you need "something".* as the entire patternerror.*.* or .*?javascript const regex = /your-pattern/g; if (regex.test("")) { throw new Error("Pattern matches empty string - DANGEROUS!"); }
^error.*.*error$\berror\bAll error patterns must pass these tests:
go// Test that pattern doesn't match empty string func TestPatternSafety(t *testing.T) { pattern := "your-pattern" regex := regexp.MustCompile(pattern) if regex.MatchString("") { t.Error("Pattern matches empty string!") } }
javascripttest("should not match empty string", () => { const regex = new RegExp("your-pattern", "g"); expect(regex.test("")).toBe(false); });
The validate_errors.cjs script has built-in protections:
regex.lastIndex stops advancingjavascript// Safety check in validate_errors.cjs if (regex.lastIndex === lastIndex) { core.error(`Infinite loop detected! Pattern: ${pattern.pattern}`); break; }
When adding new error patterns to engines:
go { Pattern: (?i)error.permission.denied, LevelGroup: 0, MessageGroup: 0, Description: "Permission denied error", }
make test-unitTestAllEnginePatternsSafePatterns are converted from Go to JavaScript:
go// Go pattern (case-insensitive flag) Pattern: `(?i)error.*permission.*denied` // Converted to JavaScript new RegExp("error.*permission.*denied", "gi")
The (?i) prefix is removed because JavaScript uses the i flag instead.
go// Requires "error" prefix Pattern: `(?i)error.*permission.*denied` // Requires specific timestamp format Pattern: `(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)\s+\[(ERROR)\]\s+(.+)` // Requires "access denied" prefix Pattern: `(?i)access denied.*user.*not authorized`
If you find a pattern that matches empty string:
Before (unsafe):
goPattern: `.*error.*` // Can match empty at start/end
After (safe):
goPattern: `error.*` // Requires "error" at start // OR Pattern: `.*error.+` // Requires "error" and at least one char after // OR Pattern: `\berror\b.*` // Requires word "error"
Before committing pattern changes:
make test-unitTestAllEnginePatternsSafe passesTestErrorPatternsNoInfiniteLoopPotential passescd pkg/workflow/js && npm testpkg/workflow/engine_error_patterns_infinite_loop_test.gopkg/workflow/js/validate_errors.test.cjspkg/workflow/error_pattern_tuning_test.goOther measured skills in the registry, with their headline benchmark lift.