Skip to content

[BUG] PDF attachment causes persistent error for all subsequent chat messages #16234

Description

@AndrewTrefilov

Description

When a PDF is attached in a conversation with a custom OpenAI-compatible endpoint backed by vLLM, the provider rejects the request. After that, every following message in the same conversation fails with the same error. The conversation cannot be recovered, only a new conversation works.

Steps to Reproduce

  1. Configure a custom OpenAI-compatible endpoint backed by vLLM in librechat.yaml.
  2. Start a conversation with that endpoint and attach a PDF file.
  3. Send the message. vLLM returns 400 Unsupported chat content part type.
  4. Send any follow-up message in the same conversation.
  5. It fails with the same error, because the PDF from the history is sent to the provider again.

The llama.cpp server behaves the same way and returns 501 Unknown part type.

Expected Behavior

  • A document the provider cannot accept should not be sent as a provider content part, or should fall back to extracted text.
  • A failed attachment should not lock the conversation, later messages should still go through.

Environment

Related

Activity

  1. AndrewTrefilov commented on Sep 23, 2026

    @AndrewTrefilov
    Author

    I checked this against the attachment routing that landed for 0.8.8 (#15763, #15937, #15940, #16027, #16058). Reading the code at v0.8.8-rc4, two parts of the problem still look open for custom OpenAI-compatible endpoints such as vLLM or the llama.cpp server.

    1. PDFs still default to the provider path on custom endpoints

    The capability gate in resolve-llm-delivery-path.ts only judges media for named endpoints:

    const canJudgeCapability = isMedia ? namedEndpoint : providerKnown;

    https://github.com/danny-avila/LibreChat/blob/v0.8.8-rc4/packages/data-provider/src/resolve-llm-delivery-path.ts#L215

    The spec pins this behaviour ("keeps documents on the provider path for a custom endpoint name"):
    https://github.com/danny-avila/LibreChat/blob/v0.8.8-rc4/packages/data-provider/src/resolve-llm-delivery-path.spec.ts#L308

    So unless an admin writes an explicit per-endpoint config, a PDF sent to vLLM is still delivered as a file content part. vLLM rejects it with 400 Unsupported chat content part type, and the llama.cpp server returns 501 Unknown part type.

    2. Conversations that already contain such a PDF stay locked

    File records created before delivery paths existed have no llmDeliveryPath. For them resolveTurnLLMDeliveryPath returns undefined:
    https://github.com/danny-avila/LibreChat/blob/v0.8.8-rc4/packages/data-provider/src/resolve-llm-delivery-path.ts#L472-L473

    BaseClient then takes the legacy branch, where application/pdf goes to addDocuments and is sent to the provider again on every turn:
    https://github.com/danny-avila/LibreChat/blob/v0.8.8-rc4/api/app/clients/BaseClient.js#L1832
    https://github.com/danny-avila/LibreChat/blob/v0.8.8-rc4/api/app/clients/BaseClient.js#L1862

    Changing the endpoint config afterwards does not help these threads, so every following message fails with the same error.

    Possible fixes

    • For custom endpoints that do not declare document support, default documents to text, or fall back to text when the provider rejects the part.
    • Treat a missing llmDeliveryPath on a stored file as "resolve again with the current routing" instead of taking the legacy branch.
  2. lia-by-librechat commented on Sep 23, 2026

    @lia-by-librechat
    Contributor

    Thanks for the detailed repro. For new PDF uploads on a build with unified file upload (this setting is not available in v0.8.7), route PDFs to extracted text instead of sending a native file part to vLLM/llama.cpp:

    fileConfig:
      endpoints:
        YourCustomEndpointName: # match the endpoint's name in librechat.yaml
          legacyFileUploadUX: false
          defaultLLMDeliveryPath:
            overrides:
              'application/pdf': text

    Please upgrade and test with a new PDF in a new conversation. The config affects new uploads, but it does not repair old file records without llmDeliveryPath: those can still be replayed as provider PDFs on subsequent turns. A new conversation is the immediate workaround for an already-stuck thread. Related DeepSeek PDF report: #16235.

  3. locked and limited conversation to collaborators on Sep 23, 2026
  4. converted this issue into a discussion #16250 on Sep 23, 2026
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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions