Skip to content

[reopen]invalid_request_error没有触发failover #5035

Closed

Description

@hnyyghk

Client or integration

Codex CLI

Area

CLI

Summary

[reopen]invalid_request_error没有触发failover

Reproduction

#4903
之前上报过这个问题,现在alibaba-token-plan/deepseek-v4.1-flash模型已经没问题了,但是换了一个deepseek/deepseek-v4-pro还是存在相同的问题

组合使用deepseek/deepseek-v4-pro和deepseek/deepseek-flash等模型时,配置为5.6-luna的影子调用拦截模型,发起新对话生成线程标题时,deepseek/deepseek-v4-pro模型因为不支持response_format,会导致invalid_request_error,但是没有继续failover到deepseek/deepseek-flash等模型执行:
Provider error 400: {"error":{"message":"This response_format type is unavailable now","type":"invalid_request_error","param":null,"code":"invalid_request_error"}}

Image

另外,除了gpt-5.6-luna外,我发现codex还会调用gpt-5.6-terra模型,是不是也需要为gpt-5.6-terra配置影子调用拦截模型?

Image

Version

2.58.0

Operating system

macOS 13.5.1

Provider and model

No response

Logs or error output

Screenshots and supporting files

No response

Redacted configuration

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

  1. added
    account-poolOAuth, credentials, Codex pool, quota, failover, plans
    cliCLI, config inject, packaging flags
    on Sep 18, 2026
  2. lidge-jun commented on Sep 18, 2026

    @lidge-jun
    Owner

    조사 결과를 공유드립니다. 결론부터 말하면 2.58.0에서는 보고하신 그대로 동작하는 것이 맞고, 수정은 이미 dev에 있으며 2.59.0에 나갑니다. 다만 "한 모델은 되고 한 모델은 안 된다"로 보였던 이유가 실제로는 실패 복구와 무관해서, 그 부분을 정확히 적어 둡니다.

    수정이 2.58.0에 들어있지 않습니다. v2.58.0 태그는 6fe4cd0de8 (2026-09-17 17:40 UTC)이고, 해당 수정 #4927은 78c71f789a (19:49 UTC)로 두 시간 여덟 분 뒤에 작성됐습니다. git merge-base --is-ancestor 78c71f789a v2.58.0 은 1로 종료하고 git tag --contains 78c71f789a 는 비어 있습니다. 즉 이 분류기가 포함된 릴리스는 아직 없습니다.

    alibaba-token-plan/deepseek-v4.1-flash 가 좋아진 것은 failover 때문이 아닙니다. #4888이 2.58.0에 들어가면서 두 Alibaba Token Plan 프리셋에 noJsonSchemaModels: ["deepseek-v4.1-flash"] 를 추가했고, src/adapters/openai-chat/passthrough.ts 가 그 모델에 대해 json_schema 요청을 json_object 로 바꿔 보냅니다. 그래서 거부 자체가 발생하지 않고 hop이 필요 없습니다. 그 프리셋 주석에 인용된 업스트림 문구가 보고하신 것과 동일합니다 — "This response_format type is unavailable now".

    두 모델의 차이는 분류기가 다르게 취급해서가 아니라, 2.58.0이 어느 쪽 대응책을 갖고 있느냐의 차이였습니다.

    deepseek/deepseek-v4-pro 도 dev 에서는 이미 hop 합니다. 보고하신 응답 본문을 파이프라인이 만들어낼 수 있는 모든 형태로 분류기에 통과시켜 확인했습니다 — 원본 본문(코드가 추출된 경우와 undefined 인 경우), Provider error 400: {...} 표시 래퍼, 단일 data: {...} SSE 프레임, 프록시 자체 재포장까지. 전부 hop 에 도달합니다.

    분류기는 손대지 않았습니다. 이 케이스가 통과할 때까지 hop 대상을 넓히는 방식은 "이 대상이 이 형태의 요청을 받을 수 없다"와 "이 요청 자체가 잘못됐다"의 구분을 무너뜨립니다. 대신 이 응답 형태를 회귀 테스트로 고정해(#5040, facd2b6ca6) 앞으로도 계속 검증되도록 했습니다.

    2.59.0이 나오면 deepseek/deepseek-v4-pro 조합을 다시 시도해 보시고, 그때도 같은 증상이면 새 보고로 올려 주세요. 그 경우는 지금과 다른 원인입니다.


    gpt-5.6-terra 질문은 별건이라 따로 확인해 답변드리겠습니다. 정확한 답을 드리려면 Codex가 실제로 어느 모델들에 대해 shadow title 호출을 내는지, 그리고 차단 모델 설정이 모델별로 설계된 것인지부터 소스로 확인해야 합니다.

  3. lidge-jun commented on Sep 18, 2026

    @lidge-jun
    Owner

    Closed via #5040 at facd2b6 (merged to dev; GitHub auto-close only applies on default main). The reported envelope already hops on dev via #4927; #5040 pins the second-gateway invalid_request_error shape.

  4. lidge-jun commented on Sep 18, 2026

    @lidge-jun
    Owner

    gpt-5.6-terra 질문에 답변드립니다. 소스로 확인한 결과, 설정 가능하고 방법이 두 가지 있습니다.

    먼저 현재 기본값입니다. src/lib/shadow-call.ts 의 DEFAULT_SHADOW_SOURCE_MODELS 는 ["gpt-5.6-luna"] 하나뿐입니다. 그래서 관찰하신 대로 gpt-5.6-terra 는 기본 차단 대상이 아닙니다.

    방법 1 — 차단 대상에 추가. sourceModels 로 기본값을 덮어쓸 수 있습니다. 매칭은 접두사 방식이라 gpt-5.6-terra 를 넣으면 뒤에 문자가 붙은 변형도 함께 잡힙니다. 다만 이 배열은 기본값을 대체하므로, 둘 다 원하시면 luna 도 같이 나열하셔야 합니다.

    방법 2 — 다른 모델로 리다이렉트. blockedModelRedirects 가 더 가까운 답일 수 있습니다. 해당 함수의 문서 주석이 쓰고 있는 예시가 정확히 { "gpt-5.6-terra": "gpt-5.6-luna" } 이고, src/router.ts:564 에서 실제로 호출됩니다. 이 경로는 요청을 대체 모델로 다시 씁니다.

    두 방법의 차이는 의도입니다. sourceModels 는 "이것도 헬퍼 호출로 간주해서 가로채라"이고, blockedModelRedirects 는 "이 모델로 가는 요청을 저 모델로 보내라"입니다. 지금 겪고 계신 상황 — terra 요청이 원치 않는 대상으로 나가는 것 — 이라면 후자가 의도에 더 맞습니다.

    참고로 라우팅된 id(provider/model 형태)는 shadow 차단에서 의도적으로 제외됩니다. shadow 호출은 항상 bare native slug이고, 사용자가 명시적으로 고른 라우팅 대상을 가로채면 안 되기 때문입니다.

    이건 기존 설정으로 해결 가능한 사안이라 별도 이슈로 열지 않았습니다. 위 두 방법 중 어느 쪽도 원하시는 동작이 안 나온다면 그때는 실제 갭이니 새로 올려 주세요.

  5. lidge-jun commented on Sep 18, 2026

    @lidge-jun
    Owner

    앞선 답변에 중요한 보완이 있습니다. 로그에 gpt-5.6-terra 가 보인다는 것이 곧 title 호출이라는 증거는 아닙니다.

    Terra는 평범한 native 모델이고 기본 subagent 모델이기도 합니다. 게다가 압축(compaction)은 routeCompactionModel 을 통해 클라이언트가 선택한 모델을 그대로 재사용합니다. 그래서 Terra 트래픽은 전경 요청일 수도, subagent 호출일 수도, 압축일 수도 있습니다 — 셋 다 helper 호출이 아닙니다.

    그리고 Terra가 기본 차단 대상에서 빠진 것은 누락이 아니라 기록된 결정입니다. devlog/_fin/260723_issue_fixes/020_issue311_shadow_intercept.md 에 "Codex가 Terra를 helper로 쓰는 캡처가 없어서 제외했고, 그것이 바뀌면 sourceModels 가 탈출구"라고 적혀 있습니다. tests/responses/responses-shadow-intercept.test.ts 의 세 케이스가 이 결정을 고정하고 있습니다.

    이게 왜 중요하냐면, Terra를 차단 대상에 넣으면 title 호출만이 아니라 모든 bare Terra 요청이 가로채집니다 — 전경 대화도, subagent 호출도요. 그래서 기본값이 아닌 것이고, 확인 없이 켜면 원치 않는 동작이 됩니다.

    그래서 권해드리는 순서는 이렇습니다. 먼저 Terra 요청이 실제로 title 생성 호출인지 확인해 주세요 — 새 대화를 열 때 나가는지, 아니면 압축이나 subagent 실행 시점에 나가는지. title 호출이 맞다면 shadowCallIntercept.sourceModels: ["gpt-5.6-luna", "gpt-5.6-terra"] 로 (Luna를 함께 나열해야 합니다 — 이 배열은 기본값을 대체합니다). Terra 자체를 쓰고 싶지 않은 것이라면 blockedModelRedirects 가 맞는 도구입니다.

    만약 캡처로 Terra의 title 호출이 확인되면 그건 기본값을 바꿀 근거가 되니 알려 주세요 — 위 devlog가 명시적으로 그 조건을 적어둔 상태입니다.

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

    account-poolOAuth, credentials, Codex pool, quota, failover, plansbugSomething isn't workingcliCLI, config inject, packaging flags

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions