Skip to content

feat: surface guardrail denial reason in 446 error message - #1740

Open
Idooran wants to merge 1 commit into
Portkey-AI:mainfrom
Idooran:feat/descriptive-guardrail-error-message
Open

feat: surface guardrail denial reason in 446 error message#1740
Idooran wants to merge 1 commit into
Portkey-AI:mainfrom
Idooran:feat/descriptive-guardrail-error-message

Conversation

@Idooran

@Idooran Idooran commented Jul 20, 2026

Copy link
Copy Markdown

Summary

When a guardrail webhook denies a request, the 446 error message is hardcoded to "The guardrail checks defined in the config failed" — which gives the end user zero context about why the request was denied.

This PR extracts the denial reason from the webhook's response data and surfaces it in the error message. For example, instead of:

The guardrail checks defined in the config failed

Users now see:

Guardrail denied the request: SSN detected in prompt. Check the `hook_results` object for details.

Changes

  • src/handlers/handlerUtils.ts: Added extractGuardrailDenyMessage() that walks hook_results to find denial reasons from responseData.reason, responseData.message, or explanation fields. Falls back to the original message if no reasons are found.
  • src/handlers/responseHandlers.ts: Uses the new function for the after-request-hook 446 path.

Backward Compatibility

  • If the webhook response doesn't include a reason, the original fallback message is returned — no breaking change.
  • The function checks responseData.reason, responseData.message, and explanation in order, accommodating different webhook response shapes.

When a webhook guardrail denies a request, the 446 error message now
includes the reason returned by the webhook (e.g. "Guardrail denied
the request: Dlp") instead of the generic "The guardrail checks
defined in the config failed" message.

This extracts the reason/message from the webhook's responseData or
explanation fields and surfaces it in the top-level error.message,
making it much easier for developers and end-users to understand
why their request was blocked without digging into hook_results.

Falls back to the original generic message when no specific reason
is available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant