Skip to content

fix(anthropic): preserve file id document sources - #4832

Merged
akshaydeo merged 1 commit into
maximhq:devfrom
mmacvicar:fix-anthropic-file-id-source
Jul 2, 2026
Merged

fix(anthropic): preserve file id document sources#4832
akshaydeo merged 1 commit into
maximhq:devfrom
mmacvicar:fix-anthropic-file-id-source

Conversation

@mmacvicar

@mmacvicar mmacvicar commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes Anthropic document conversion when Bifrost receives an OpenAI-compatible chat completion request that references an uploaded Anthropic file by file_id.

When This Happens

When the routed model is Anthropic and the message contains a file content block like below on OpenAI-compatible routes such as /litellm/v1/chat/completions or /v1/chat/completions, Bifrost converts that OpenAI-compatible file block into an Anthropic document block. Before this fix, uploaded file_id references were not copied into the Anthropic document source object, and source.type was not set to file, causing Anthropic to reject the request.

OpenAI-compatible input:

{
  "type": "file",
  "file": {
    "file_id": "file_abc123",
    "filename": "tiny.pdf"
  }
}

The failure happens while converting the OpenAI-compatible chat request into Anthropic Messages API content blocks. Before the fix, Bifrost produced an Anthropic document block with an initialized but invalid source object:

{
  "type": "document",
  "title": "tiny.pdf",
  "source": {
    "type": ""
  }
}

Anthropic rejects this because document.source.type must be one of its supported source tags, for example file, base64, url, or text. After the fix, Bifrost preserves the uploaded file reference in Anthropic's expected file-source shape:

{
  "type": "document",
  "title": "tiny.pdf",
  "source": {
    "type": "file",
    "file_id": "file_abc123"
  }
}

Reproduction

A self-contained reproduction case is documented here:

talismanai/bifrost-issue: anthropic-file-id-openai-route

That case contains the run instructions, a self-contained uv sample script, and the Bifrost configuration used for local validation. The script uploads a tiny PDF to POST /v1/files?provider=anthropic, calls POST /litellm/v1/chat/completions with the uploaded file_id, prints the response, and deletes the uploaded file.

git clone git@github.com:talismanai/bifrost-issue.git
cd bifrost-issue/cases/anthropic-file-id-openai-route
BIFROST_URL="http://localhost:8080" BIFROST_API_KEY="..." uv run python repro.py

Changes

  • Map ChatInputFile.FileID to Anthropic source: {type: "file", file_id: ...}.
  • Add a regression test for the LiteLLM/OpenAI-compatible payload shape.
  • Update core/changelog.md.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

go test ./providers/anthropic ./providers/openai
go vet ./providers/anthropic
git diff --check

For end-to-end validation, run the external reproduction case linked above against a local Bifrost gateway configured with an Anthropic key and the anthropic-beta: files-api-2025-04-14 header.

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

No new auth, secret, or data exposure paths. This only preserves an existing uploaded file ID in the downstream Anthropic request body. The external repro reads credentials from environment variables only.

Checklist

  • I read the contribution guidelines and followed the applicable parts
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed for the touched Go packages
  • I verified the full CI pipeline passes locally if applicable

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 975732fd-18c5-4e67-885f-089e8cb62407

📥 Commits

Reviewing files that changed from the base of the PR and between a52d180 and 8158040.

📒 Files selected for processing (3)
  • core/changelog.md
  • core/providers/anthropic/chat_test.go
  • core/providers/anthropic/utils.go

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Preserved uploaded file references when converting document content, so file-based attachments continue to use the correct source information.
    • Improved handling of file attachments from OpenAI-compatible requests, including file name and file ID details.
  • Tests
    • Added coverage for converting uploaded file blocks into document sources with the expected file-based metadata.
  • Documentation
    • Updated the changelog with the latest fix.

Walkthrough

This PR fixes Anthropic document block conversion to preserve OpenAI-compatible uploaded file references (FileID) as a file-type document source, adds a test verifying the conversion, and includes a corresponding changelog entry.

Changes

Anthropic file source fix

Layer / File(s) Summary
FileID handling in document block conversion
core/providers/anthropic/utils.go
ConvertToAnthropicDocumentBlock now checks for file.FileID first and, if present, sets the document source type to "file" with the FileID assigned, returning early before the existing FileURL/FileData handling.
Conversion test and changelog
core/providers/anthropic/chat_test.go, core/changelog.md
Adds sonic and OpenAI request imports, a new test constructing an OpenAI-compatible file content block and asserting the resulting Anthropic document block uses a file source with file_id, and a changelog bullet documenting the fix.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested reviewers: akshaydeo, danpiths

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main fix: preserving Anthropic file_id document sources.
Description check ✅ Passed The description follows the template and includes the required summary, changes, testing, areas, and checklist sections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@CLAassistant

CLAassistant commented Jul 1, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Preserves uploaded file references when OpenAI-compatible chat file blocks are converted into Anthropic document blocks.

Affected packages:

- core/providers/anthropic/ - document block conversion and regression coverage

- core/changelog.md - user-facing changelog entry
@mmacvicar
mmacvicar force-pushed the fix-anthropic-file-id-source branch 2 times, most recently from 3aa12d8 to 8158040 Compare July 1, 2026 18:51
@mmacvicar
mmacvicar marked this pull request as ready for review July 1, 2026 18:53
@coderabbitai
coderabbitai Bot requested review from akshaydeo and danpiths July 1, 2026 18:54
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — the change is a minimal, targeted fix to a single conversion function with no side effects on other source types.

The fix adds one guard branch in a pure conversion function, consistent with existing patterns for url and base64 sources. The regression test drives the full conversion chain and asserts both the source type and file_id value. No other code paths are affected.

No files require special attention.

Important Files Changed

Filename Overview
core/providers/anthropic/utils.go Adds file_id handling as the first branch in ConvertToAnthropicDocumentBlock, consistent with the existing pointer-assignment pattern for URL and data sources; correct and minimal.
core/providers/anthropic/chat_test.go New regression test covers the full OpenAI-compatible → Bifrost → Anthropic pipeline for a file_id document source block; assertions are complete and correct.
core/changelog.md Prepends the fix entry at the top of the changelog; no issues.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client
    participant Bifrost
    participant ConvertDocBlock as ConvertToAnthropicDocumentBlock
    participant Anthropic

    Client->>Bifrost: POST /litellm/v1/chat/completions
    Bifrost->>Bifrost: ToBifrostChatRequest()
    Bifrost->>ConvertDocBlock: "block.File.FileID = file_abc123"
    ConvertDocBlock->>ConvertDocBlock: "FileID != nil → source.type=file"
    ConvertDocBlock-->>Bifrost: "AnthropicContentBlock{source:{type:file,file_id:file_abc123}}"
    Bifrost->>Anthropic: POST /v1/messages
    Anthropic-->>Bifrost: 200 OK
    Bifrost-->>Client: response
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Client
    participant Bifrost
    participant ConvertDocBlock as ConvertToAnthropicDocumentBlock
    participant Anthropic

    Client->>Bifrost: POST /litellm/v1/chat/completions
    Bifrost->>Bifrost: ToBifrostChatRequest()
    Bifrost->>ConvertDocBlock: "block.File.FileID = file_abc123"
    ConvertDocBlock->>ConvertDocBlock: "FileID != nil → source.type=file"
    ConvertDocBlock-->>Bifrost: "AnthropicContentBlock{source:{type:file,file_id:file_abc123}}"
    Bifrost->>Anthropic: POST /v1/messages
    Anthropic-->>Bifrost: 200 OK
    Bifrost-->>Client: response
Loading

Reviews (1): Last reviewed commit: "[fix]: Anthropic provider - preserve fil..." | Re-trigger Greptile

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.

4 participants