Skip to content

hive (openai-chat): upstream 400 is terminal so combo cannot fail over; developer role and non-text content parts are rejected #6409

Closed as not planned

Description

@the-ocean-lab

Summary

On the hive provider (thehive.ai, adapter openai-chat) requests to /v1/chat/completions intermittently fail with an upstream 400 that opencodex reports as terminal, so a combo has nothing to fail over to and the turn dies:

{"error":{"message":"Provider error 400: {\"status_code\":400,\"message\":\"Received bad JSON request\"}","type":"invalid_request_error","code":"invalid_request_error"}}

In the trace I looked at, one conversation had 176 successful turns, then a burst of 400s (~7 in ~100s), then normal service resumed after auto-compaction. So it is not a hard outage: the gateway rejects a specific request shape, and the same route serves the next request fine.

Environment

  • opencodex 2.75.0
  • provider hive: baseUrl https://api-cdn.thehive.ai/api/v3, adapter openai-chat, authMode key
  • model deepseek-ai/deepseek-v4.1-flash (also zai-org/glm-5.3-flash)
  • reproduced both directly against hive/deepseek-ai/deepseek-v4.1-flash and via combo/hive-fb (single target, strategy failover)

Reproductions

POST http://127.0.0.1:10102/v1/chat/completions, model hive/deepseek-ai/deepseek-v4.1-flash:

Request body Result
messages[0] = {"role":"developer","content":"be terse"} 400 Provider error 400: Bad Request
messages[0] = {"role":"developer","content":[{"type":"text","text":"be terse"}]} 400 Provider error 400: Bad Request
messages[0] = {"role":"system","content":"be terse"} 200
messages[0] = {"role":"system","content":[{"type":"text","text":"be terse"}]} 200
messages[0] = {"role":"system","content":[{"type":"input_text","text":"be terse"}]} 400 Provider error 400: Bad Request
content contains a lone/unpaired surrogate, e.g. "...AB\ud800CD..." (valid JSON per RFC 8259) 400 Provider error 400: Invalid payload: Missing model name
content contains a matched surrogate pair (\ud83d\ude00) 200
2 MB body / ~700k-token prompt 200 (size/length is not the trigger; 4 MB returns a different, honest Please reduce the length… error)

Findings: the Hive gateway rejects (a) the developer role and (b) any content part that is not {"type":"text",...}. It also mis-parses lone surrogates.

Why this is worth fixing in opencodex

  1. comboFailureDecision treats this as terminal. The upstream code is invalid_request_error, which the classifier maps to "stop", so a combo cannot hop even though the next target could serve the request. These look like request-local target incompatibilities (bad/decorated body for this gateway), which the hop rules already handle for other shapes.

  2. The hive destination's quirks are not recorded. The translated chat route folds developer → system only for the unrecorded default, and the native passthrough forwards roles verbatim unless foldDeveloperRoleToSystem is set for that destination. Recording foldDeveloperRoleToSystem: true for hive, plus sanitizing input_text-style parts and lone surrogates before the wire, would stop the failures at the source.

Asks

  • Record the hive capability facts (rejects developer; rejects non-text content parts; rejects lone surrogates) so the request is normalized rather than refused.
  • Classify this class of upstream invalid_request_error payload-shape 400 as request-local/target-local so a combo can fail over instead of ending the turn.

Note

I could not isolate the exact Received bad JSON request string with a synthetic body; it appears to be Hive's JSON-parser layer reporting the same class of body it rejects (the sibling messages above are deterministic). Happy to share raw request bodies/traces if useful.

Activity

  1. github-actions commented on Oct 1, 2026

    @github-actions
    Contributor

    Automated translation bookkeeping — detected language: English.

  2. github-actions commented on Oct 1, 2026

    @github-actions
    Contributor

    Issue closed: use an issue template

    Thanks for taking the time to submit this issue. It was closed automatically because it was not opened with a recognized issue template (Bug report, Feature request, Documentation, or Provider compatibility). Freeform and API-opened issues cannot skip this check.

    • This issue does not use a recognized issue template.

    Please edit the issue to add:

    • Open a new issue with the Bug report, Feature request, Documentation, or Provider compatibility template.
    • Or edit this issue so the body uses the template section headings for the kind of report you are filing.

    See the Contributing guide for details.

    Once the report passes the automated checks, it will be reopened automatically unless a maintainer has changed its state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions