Description
Three distinct Vertex AI failure modes all produce the same OpenCode UI error message — "The response was blocked by the provider's content filter" — making it impossible to diagnose the actual problem without instrumenting raw API calls against the Vertex endpoint directly.
This conflation was already partially addressed in #31744 / #31745, but the fix did not cover the 404 and socket-close cases, and the stop_reason: refusal case still doesn't include the refusal category or explanation in the UI.
Environment
- OpenCode 1.17.14
- Provider:
google-vertex, model claude-opus-4-8@default
- macOS, Homebrew install
Three failure modes, one error message
Mode 1: 404 NOT_FOUND (model unavailable in region)
claude-opus-4-8@default returns HTTP 404 on regional Vertex endpoints. When the google-vertex provider routes to a regional endpoint (e.g. us-central1) instead of global, every request silently fails.
Log: No error written. Session idles. UI shows "blocked by content filter."
Raw API response: HTTP 404, "status": "NOT_FOUND"
Expected UI message: something like "Model not found on this endpoint (404) — check your Vertex region configuration"
Mode 2: Socket close / connection reset
Seen in logs from June 2026 on longer sessions with Opus:
AI_APICallError: Cannot connect to API: The socket connection was closed unexpectedly.
Log: ERROR written, but UI still shows "blocked by content filter."
Expected UI message: "Connection to Vertex AI was dropped — this may be a transient error, retry or check your network"
Mode 3: True content refusal (stop_reason: refusal)
When the system prompt contains content that triggers Anthropic's real-time cyber safeguards, Vertex returns HTTP 200 with:
{
"stop_reason": "refusal",
"stop_details": {
"type": "refusal",
"category": "cyber",
"explanation": "This request triggered restrictions on violative cyber content..."
}
}
Log: No error written. Session idles. UI shows "blocked by content filter."
Expected UI message: something like "Response refused by provider (category: cyber) — review your system prompt for content that may trigger safety filters"
Why this matters
In the case above, diagnosing the actual root cause required:
- Grepping the log file to find that no error was written (ruling out a logged failure)
- Manually replicating the request with
curl against the Vertex API
- Discovering the 404 — which revealed the region routing bug
- After fixing routing, re-running
curl with the full system prompt to discover the true stop_reason: refusal with category: cyber
- Bisecting the system prompt to find the triggering content
All of this was opaque from the OpenCode UI. The same "blocked by content filter" message was shown throughout, regardless of which failure mode was active.
Suggested improvements
-
Distinguish HTTP errors from finish-reason errors. A 404 from the Vertex endpoint is not a content filter — it's a configuration/routing error. Show the HTTP status and a hint.
-
For stop_reason: refusal, include the category and explanation fields from stop_details in the visible error message. Anthropic includes actionable text in these fields (e.g. "category: cyber", link to help article) that is currently swallowed entirely.
-
For socket close errors, show a distinct "connection dropped" message rather than conflating with content filter.
-
Write an error log entry for all three cases. Mode 1 (404) and Mode 3 (refusal) currently produce no ERROR-level log entry, making post-hoc debugging harder.
Steps to Reproduce
Mode 1: 404 (model unavailable in region)
Prerequisites: Google Cloud project with Vertex AI enabled, ADC configured (gcloud auth application-default login).
- Set
GOOGLE_CLOUD_PROJECT but do not set GOOGLE_VERTEX_LOCATION or GOOGLE_CLOUD_LOCATION — only set VERTEX_LOCATION=global (or leave all location env vars unset).
- In OpenCode, select
google-vertex / claude-opus-4-8@default.
- Send any message.
- Expected: an error indicating the model was not found or the endpoint is wrong.
- Actual: UI shows "The response was blocked by the provider's content filter." Log shows no ERROR entry. Session idles.
To confirm the underlying error independently:
curl -s -w "\nHTTP:%{http_code}" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-X POST "https://us-central1-aiplatform.googleapis.com/v1/projects/${GOOGLE_CLOUD_PROJECT}/locations/us-central1/publishers/anthropic/models/claude-opus-4-8@default:streamRawPredict" \
-d '{"anthropic_version":"vertex-2023-10-16","max_tokens":10,"messages":[{"role":"user","content":"hello"}]}'
# Returns HTTP 404 NOT_FOUND
Mode 3: stop_reason: refusal (content safety)
Prerequisites: same as above, but with GOOGLE_VERTEX_LOCATION=global correctly set so the model is reachable.
-
Create an AGENTS.md (or any project rules file) containing security/hardware content — for example, references to low-level disk write operations, exploit toolchain usage, or root SSH access patterns. A minimal synthetic example that triggers the classifier:
## Hardware access
Use `ssh root@192.168.1.1` with key at `~/.ssh/id_ed25519`.
Run the exploit tool: sector args are hex (`sscanf("%x")`).
Write sectors with EMMC_WRITE; verify with SHA256 readback.
Use debugfs -w to write files; note exit 0 does not confirm success.
-
In OpenCode, select google-vertex / claude-opus-4-8@default.
-
Send any message (e.g. "Hello").
-
Expected: an error indicating the response was refused, with the refusal category (cyber) and a pointer to review the system prompt.
-
Actual: UI shows "The response was blocked by the provider's content filter" with no category, no explanation, and no log entry. Indistinguishable from Mode 1.
To confirm the underlying response independently:
curl -s \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-X POST "https://aiplatform.googleapis.com/v1/projects/${GOOGLE_CLOUD_PROJECT}/locations/global/publishers/anthropic/models/claude-opus-4-8@default:streamRawPredict" \
-d '{
"anthropic_version": "vertex-2023-10-16",
"max_tokens": 50,
"system": "Use ssh root@192.168.1.1 with key at ~/.ssh/id_ed25519. Run exploit tool: sector args are hex. Write with EMMC_WRITE, verify SHA256. Use debugfs -w.",
"messages": [{"role": "user", "content": "Hello"}]
}'
# Returns HTTP 200 with stop_reason: "refusal", stop_details.category: "cyber"
Note: the synthetic prompt above is the minimal trigger found during investigation. The actual content that triggered this in production was a project AGENTS.md describing legitimate hardware development workflows — the classifier does not distinguish intent.
References
Plugins
No response
OpenCode version
No response
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response
Description
Three distinct Vertex AI failure modes all produce the same OpenCode UI error message — "The response was blocked by the provider's content filter" — making it impossible to diagnose the actual problem without instrumenting raw API calls against the Vertex endpoint directly.
This conflation was already partially addressed in #31744 / #31745, but the fix did not cover the 404 and socket-close cases, and the
stop_reason: refusalcase still doesn't include the refusal category or explanation in the UI.Environment
google-vertex, modelclaude-opus-4-8@defaultThree failure modes, one error message
Mode 1: 404 NOT_FOUND (model unavailable in region)
claude-opus-4-8@defaultreturns HTTP 404 on regional Vertex endpoints. When thegoogle-vertexprovider routes to a regional endpoint (e.g.us-central1) instead ofglobal, every request silently fails.Log: No error written. Session idles. UI shows "blocked by content filter."
Raw API response:
HTTP 404, "status": "NOT_FOUND"Expected UI message: something like "Model not found on this endpoint (404) — check your Vertex region configuration"
Mode 2: Socket close / connection reset
Seen in logs from June 2026 on longer sessions with Opus:
Log: ERROR written, but UI still shows "blocked by content filter."
Expected UI message: "Connection to Vertex AI was dropped — this may be a transient error, retry or check your network"
Mode 3: True content refusal (stop_reason: refusal)
When the system prompt contains content that triggers Anthropic's real-time cyber safeguards, Vertex returns HTTP 200 with:
{ "stop_reason": "refusal", "stop_details": { "type": "refusal", "category": "cyber", "explanation": "This request triggered restrictions on violative cyber content..." } }Log: No error written. Session idles. UI shows "blocked by content filter."
Expected UI message: something like "Response refused by provider (category: cyber) — review your system prompt for content that may trigger safety filters"
Why this matters
In the case above, diagnosing the actual root cause required:
curlagainst the Vertex APIcurlwith the full system prompt to discover the truestop_reason: refusalwithcategory: cyberAll of this was opaque from the OpenCode UI. The same "blocked by content filter" message was shown throughout, regardless of which failure mode was active.
Suggested improvements
Distinguish HTTP errors from finish-reason errors. A 404 from the Vertex endpoint is not a content filter — it's a configuration/routing error. Show the HTTP status and a hint.
For
stop_reason: refusal, include thecategoryandexplanationfields fromstop_detailsin the visible error message. Anthropic includes actionable text in these fields (e.g. "category: cyber", link to help article) that is currently swallowed entirely.For socket close errors, show a distinct "connection dropped" message rather than conflating with content filter.
Write an error log entry for all three cases. Mode 1 (404) and Mode 3 (refusal) currently produce no ERROR-level log entry, making post-hoc debugging harder.
Steps to Reproduce
Mode 1: 404 (model unavailable in region)
Prerequisites: Google Cloud project with Vertex AI enabled, ADC configured (
gcloud auth application-default login).GOOGLE_CLOUD_PROJECTbut do not setGOOGLE_VERTEX_LOCATIONorGOOGLE_CLOUD_LOCATION— only setVERTEX_LOCATION=global(or leave all location env vars unset).google-vertex/claude-opus-4-8@default.To confirm the underlying error independently:
Mode 3: stop_reason: refusal (content safety)
Prerequisites: same as above, but with
GOOGLE_VERTEX_LOCATION=globalcorrectly set so the model is reachable.Create an
AGENTS.md(or any project rules file) containing security/hardware content — for example, references to low-level disk write operations, exploit toolchain usage, or root SSH access patterns. A minimal synthetic example that triggers the classifier:In OpenCode, select
google-vertex/claude-opus-4-8@default.Send any message (e.g. "Hello").
Expected: an error indicating the response was refused, with the refusal category (
cyber) and a pointer to review the system prompt.Actual: UI shows "The response was blocked by the provider's content filter" with no category, no explanation, and no log entry. Indistinguishable from Mode 1.
To confirm the underlying response independently:
Note: the synthetic prompt above is the minimal trigger found during investigation. The actual content that triggered this in production was a project
AGENTS.mddescribing legitimate hardware development workflows — the classifier does not distinguish intent.References
Plugins
No response
OpenCode version
No response
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response