Files
onyx/mobile/src
roshan aaa78990a6 fix(chat): show blocked and redirected custom tool calls as failed (#16368)
## Description

Part 3 of the
[ENG-4416](https://linear.app/onyx-app/issue/ENG-4416/ux-plugins-and-tool-flow-nits)
stack. A custom tool call blocked by the SSRF check (or answered with a
redirect) raised `ToolCallException` before any `CustomToolDelta`, so
the step list said "get_meta_data completed".

- `CustomTool.run()` now returns a failed `CustomToolCallSummary` and
emits a `CustomToolDelta` with `CustomToolErrorInfo` for blocked
destinations (`status_code=None`) and redirects (the 3xx code). This
reuses the existing 401/403 error path, so the error also persists in
history.
- `CustomToolRenderer` shows "{tool} was blocked" with the error icon
and error surface. HTTP failures keep "{tool} failed ({code})".
- The LLM gets the same short message the user sees.

| Before | After | After reload | Mobile |
| --- | --- | --- | --- |
|
![before](https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmdfT2NlNnlnR2RrdGJQekZsaS8xN2M4NzBmOC1mN2QxLTRhZmMtOTJlOS05MjA3ZjIyOTY0MDYiLCJpYXQiOjE3OTI1NTczOTIsIm9yZ19pZCI6Im9yZ19PY2U2eWdHZGt0YlB6RmxpIiwiZmlsZW5hbWUiOiJibG9ja2VkLXRvb2wtZG9uZS5wbmcifQ._FurQrQrApzCTY8kfPRGGceyXv67CDXPMWarqGRUUag)
|
![after](https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmdfT2NlNnlnR2RrdGJQekZsaS80OGE0MTRhMS1lNWI5LTRkOTItYjhiYy0zOWJmMTg2ZDI3NjMiLCJpYXQiOjE3OTI1NTczOTIsIm9yZ19pZCI6Im9yZ19PY2U2eWdHZGt0YlB6RmxpIiwiZmlsZW5hbWUiOiJibG9ja2VkLXRvb2wtZXhwYW5kZWQtZGVza3RvcC5wbmcifQ.w3cJq2pLwzEQ0tTFWZhFen_3Er4C2obm7e5Fj8PikN4)
|
![reload](https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmdfT2NlNnlnR2RrdGJQekZsaS80OTMwMDJjMC1kYmVjLTQxZmMtYWIwNy1mOGYzODE4Y2Y5NWMiLCJpYXQiOjE3OTI1NTczOTIsIm9yZ19pZCI6Im9yZ19PY2U2eWdHZGt0YlB6RmxpIiwiZmlsZW5hbWUiOiJibG9ja2VkLXRvb2wtcmVsb2FkLWRlc2t0b3AucG5nIn0.G6jDHd5gN_Dre0utwEEP0H1kT60stetm-L-7Pqzj6iQ)
|
![mobile](https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmdfT2NlNnlnR2RrdGJQekZsaS9lMWM1NjQwNS1hM2FhLTQ5YjgtYWU0Mi1iNDBhZjRlYzA4OTUiLCJpYXQiOjE3OTI1NTczOTIsIm9yZ19pZCI6Im9yZ19PY2U2eWdHZGt0YlB6RmxpIiwiZmlsZW5hbWUiOiJibG9ja2VkLXRvb2wtZXhwYW5kZWQtbW9iaWxlLnBuZyJ9.6i7DBU4S-6P9fvgrfKT_U1QV9DgxS39apmJ16CnzL_0)
|


![flow](https://app.devin.ai/api/presigned_proxy?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjpudWxsLCJidWNrZXRfbmFtZSI6ImRldmluYXR0YWNobWVudHMiLCJidWNrZXRfa2V5IjoiYXR0YWNobWVudHNfcHJpdmF0ZS9vcmdfT2NlNnlnR2RrdGJQekZsaS8wMjhlZjM4Ni0zYTcyLTQ0NzItYTZlMi1mMTllODhiNzQ5OWMiLCJpYXQiOjE3OTI1NTczOTIsIm9yZ19pZCI6Im9yZ19PY2U2eWdHZGt0YlB6RmxpIiwiZmlsZW5hbWUiOiJhZnRlci1ibG9ja2VkLWRlc2t0b3Aud2VicCJ9.tFAbmOk535udvZk_wDwUrQ5MBvYyGyCWZ0-laqVKlLs)

The last "Done" row is the timeline's turn-finished step (`showDoneStep`
in `useTimelineUIState`), shown for every finished turn. It no longer
reads as the tool's result.

## How Has This Been Tested?

- Local ODS stack + gpt-4.1-mini: an OpenAPI plugin on
`169.254.169.254.nip.io`; asked chat to call it. Desktop, reload and
mobile show "was blocked" and no "completed"; API log shows the
metadata-IP refusal.
- `pytest backend/tests/unit/onyx/tools/custom`: 105 passed (blocked,
redirect, and delta/summary parity cases).
- New `CustomToolRenderer.test.tsx` (blocked + HTTP failure).
- `pre-commit` (ty, ruff, tsc, oxlint) on touched files.

## Additional Options

- [x] [Optional] Please cherry-pick this PR to the latest release
version.


Link to Devin session:
https://app.devin.ai/sessions/09df74c24e19407bbf0e7ab775b5cb0a
Open in Devin Desktop:
https://app.devin.ai/desktop/session/09df74c24e19407bbf0e7ab775b5cb0a?variant=devin
Requested by: @rohoswagger

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes custom tool calls blocked by the SSRF check or answered with a
redirect so they show as failed instead of "completed" in the chat step
list.

- `CustomTool.run()` now returns a failed `CustomToolCallSummary` and
emits a `CustomToolDelta` with error info for blocked destinations and
redirects instead of raising `ToolCallException`, reusing the existing
401/403 error path so the error persists in history.
- `CustomToolRenderer` shows "{tool} was blocked" with the error icon
and error surface; HTTP failures keep "{tool} failed ({code})".
- The LLM receives the same short message the user sees.

<sup>Written for commit 29b59437a1.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/onyx-dot-app/onyx/pull/16368?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="View guided diff"
src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a>
<a
href="https://www.cubic.dev/action/auto-fix/pr/onyx-dot-app/onyx/16368?returnTo=https%3A%2F%2Fgithub.com%2Fonyx-dot-app%2Fonyx%2Fpull%2F16368&source=description"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img
alt="Turn on auto-fix"
src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->

## Summary by CodeRabbit

- **Bug Fixes**
- Custom tool requests blocked by security checks or redirects now
appear as structured failures instead of unexpected errors.
- Error details, including HTTP status codes where available, are
consistently shown in the conversation.
- Blocked and authentication-related errors now display clear,
non-collapsible status messages.

- **Localization**
  - Added blocked-tool status translations across supported languages.

- **Tests**
- Added coverage for blocked destinations, redirects, HTTP failures, and
error rendering.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-10-21 17:06:14 +00:00
..