Skip to content

[Bug]: VolcEngine/Ark provider crashes with AttributeError when key is a JSON non-object (same pattern as #17204 / #17373 / #17389) #17456

Description

@Harsh23Kashyap

Self Checks

  • I have searched for existing issues, including closed ones.
  • I confirm that I am using English to submit this report.
  • Non-English title submissions will be closed directly.
  • I have not modified the template and have filled in all the required fields.

RAGFlow workspace code commit ID

main @ 326893811 (also reproducible on 0a8f28ff3 and any prior v0.26.x).

RAGFlow image version

v0.26.4 (also reproducible on the current dev image).

Other environment information

  • Provider: VolcEngine (factory name), aka ByteDance Volcengine Ark (https://ark.cn-beijing.volces.com/api/v3)
  • Affected classes: VolcEngineChat (rag/llm/chat_model.py:965), VolcEngineCV (rag/llm/cv_model.py:614), VolcEngineEmbed (rag/llm/embedding_model.py:1086)

Actual behavior

The VolcEngine/Ark provider in rag/llm/ parses its API key as JSON, looking for ark_api_key, ep_id, and endpoint_id. The current code has a partial try/except around the parse:

# rag/llm/chat_model.py:975 (also in cv_model.py:621 and embedding_model.py:1100)
try:
    ark_api_key = json.loads(key).get("ark_api_key", "")
    model_name = json.loads(key).get("ep_id", "") + json.loads(key).get("endpoint_id", "")
    super().__init__(ark_api_key, model_name, base_url, **kwargs)
except JSONDecodeError:
    super().__init__(key, model_name, base_url, **kwargs)

except JSONDecodeError only catches the case where the string fails to parse as JSON. It does NOT catch AttributeError from .get(...) when the parsed JSON is not an object — for example:

  • key = '[1, 2, 3]' parses to a list → .get("ark_api_key", "") raises AttributeError: 'list' object has no attribute 'get'
  • key = '"a plain string"' parses to a string → same AttributeError
  • key = 'null' parses to None → same AttributeError
  • key = '42' parses to int → same AttributeError
  • key = 'true' parses to bool → same AttributeError
  • key = '[1, 2]' (a JSON array) → same AttributeError

In every case the call site raises an unhandled AttributeError that bubbles up as a 500 in the API and a stack trace in the server log. This is the same class of bug that PR #17215 fixed for Azure, PR #17377 fixed for Bedrock, and PR #17390 fixed for BaiduYiyan. The VolcEngine call sites are the only remaining unfixed LLM-provider JSON-decode sites in rag/llm/.

Expected behavior

A user pasting any non-VolcEngine-shaped key (a plain API key, a JSON list, a JSON number, a malformed JSON object) should get a clear, actionable error at provider-init time, not a 500. The existing fallback for plain-string keys (use the raw key as ark_api_key) is reasonable and should be preserved. A JSON non-object should raise the same ModelException family the other provider helpers raise, pointing the user at the required schema.

Steps to reproduce

  1. Start RAGFlow v0.26.4 (any deployment).
  2. Try to add a VolcEngine model provider via the admin UI (or POST /api/v1/llm/factories).
  3. Paste any of these into the API key field:
    • A plain AWS-style key like "AKLA..." — works (falls through to the JSONDecodeError branch and uses the raw string).
    • A JSON array like ["a", "b"] — crashes with AttributeError: 'list' object has no attribute 'get'.
    • A JSON number like 42 — same crash.
    • A JSON string like "a plain string" (with quotes) — same crash.
    • A JSON null null — same crash.
  4. The server log shows an unhandled AttributeError. The admin UI shows a generic 500 with no actionable hint.

Expected error surface

After the fix, a JSON non-object should raise the same clear error as the other provider helpers (e.g. ModelException(retryable=False) with a message like: "VolcEngine requires a JSON object with 'ark_api_key' and ('ep_id' or 'endpoint_id'); got <type>").

The plain-string-key fallback should be preserved (the existing partial handler is correct for that case).

Additional information

Affected files and line numbers (in commit 326893811):

File Class Lines
rag/llm/chat_model.py VolcEngineChat 975-980
rag/llm/cv_model.py VolcEngineCV 621-627
rag/llm/embedding_model.py VolcEngineEmbed 1100-1106

All three sites use the same try/except JSONDecodeError pattern and have the same bug shape. The fix should be a single helper in rag/llm/key_utils.py (following the established pattern for _resolve_bedrock_credentials and _resolve_qianfan_credentials) wired into all three call sites, with regression tests covering:

  1. Plain string key → ark_api_key = key, model_name derived from passed arg (preserves existing fallback)
  2. JSON dict with all fields → ark_api_key = cfg["ark_api_key"], model_name = cfg["ep_id"] + cfg["endpoint_id"] (preserves existing happy path)
  3. JSON dict missing some fields → cfg.get(k, "") defaults (preserves existing tolerance)
  4. JSON list, number, string, null, bool → ModelException (the new fix)
  5. Bad JSON string → ModelException (the new fix) — currently the JSONDecodeError branch silently uses the raw string, which is the existing partial fix; this PR can keep that behavior or upgrade it to ModelException for consistency with the other helpers
  6. Helper propagates the right fields to the call site so each model type (chat / cv / embed) gets exactly what it needs

A PR fixing this is in progress.

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