Skip to content

bug: detect_regex_pattern() matches during output streaming but does not block #1936

Description

@m-misiura

Did you check docs and existing issues?

  • I have read all the NeMo-Guardrails docs
  • I have updated the package to the latest version before submitting this issue
  • (optional) I have used the develop branch
  • I have searched the existing issues of NeMo-Guardrails

Python version (python --version)

Python 3.12.0

Operating system/version

26.5

NeMo-Guardrails version (if you must use a specific version and not the latest

0.22.0

Describe the bug

The built-in detect_regex_pattern action correctly detects forbidden regex patterns during streaming output rail execution (logs confirm the match), but the streaming framework does not block the content. The matched output is streamed to the client as if no violation occurred.

Steps To Reproduce

  1. Configure output rails with streaming enabled and regex check output:, e.g.
models:
  - type: main
    engine: openai
    parameters:
      base_url: "https://INSERT_ME/v1"
      model_name: "INSERT_ME"
      api_key: "INSERT_ME"

rails:
  output:
    flows:
      - regex check output
    streaming:
      enabled: true
      chunk_size: 200
      context_size: 50
      stream_first: true

  config:
    regex_detection:
      output:
        patterns:
          - "\\bconfidential\\b"
          - "\\bsecret\\b"

streaming: true
  1. Start the server
  2. Send a request, e.g.
curl -N -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "your-model",
    "messages": [{"role": "user", "content": "Tell me about the movie Fight Club"}],
    "stream": true
  }'
  1. Observe the logs:
INFO:nemoguardrails.actions.action_dispatcher:Executing registered action: detect_regex_pattern
INFO:nemoguardrails.library.regex.actions:Regex pattern matched: \bfight\s+club\b

The pattern matches, but the response is not blocked; the full LLM output streams to the client

Expected Behavior

When the regex pattern matches in a streaming output chunk, the stream should be terminated and a guardrails violation error should be returned:

{"error": {"message": "Blocked by regex check output rails.", "type": "guardrails_violation", "param": "regex check output", "code": "content_blocked"}}

Actual Behavior

The regex match is logged but the content streams through unblocked. No error is returned to the client.

Cause

  • is_output_blocked looks for an output_mapping function attached to the action's metadata. If none is found, it falls back to default_output_mapping
  • detect_regex_pattern returns a RegexDetectionResult (a TypedDict / dict)
  • Since a dict is not bool and not int/float, default_output_mapping returns False — meaning "not blocked" — regardless of what is_match says.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstatus: needs triageNew issues that have not yet been reviewed or categorized.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions