Question Classifier can fail with JSONDecodeError "Extra data" when model returns multiple JSON objects
まだ誰も着手していません。
評価
調査の方向性
api/libs/json_in_md_parser.py の parse_json_markdown() から始め、issue に示されている 2 オブジェクトの入力で失敗を再現します。最初の値をパースするアプローチを試す前に、既存の fenced content 用フォールバックと期待されるキーの検証を確認します。既存のフォールバックと検証の動作を維持したまま、最初の有効な JSON 値が Extra data なしでパースされれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Self Checks
- I have read the Contributing Guide and searched for existing issues, including closed ones.
- This is a bug report.
- I am submitting this report in English.
Dify version
Observed on self-hosted Dify app version 1.13.3 (Enterprise chart 3.9.10 and 3.9.11). The same parser implementation is still present on current main in api/libs/json_in_md_parser.py.
Cloud or Self Hosted
Self Hosted
Steps to reproduce
The failure occurs when a Question Classifier model returns more than one JSON object without a code fence.
A minimal parser-level reproduction is:
from libs.json_in_md_parser import parse_json_markdown
text = '{"a": 1}\n{"a": 2}'
parse_json_markdown(text)
parse_json_markdown() finds the first opening { but uses rfind("}") / rfind("]") to determine the end of the JSON block. Therefore the extracted slice contains both JSON objects:
{"a": 1}
{"a": 2}
Passing that slice to json.loads() raises:
json.decoder.JSONDecodeError: Extra data
In a real Question Classifier workload we reproduced the same class of failure at low load, so it is not a saturation/concurrency issue. The exact Extra data position varies because the model output shape is nondeterministic.
Expected Behavior
Question Classifier should parse the first valid JSON object returned by the model, or otherwise reject malformed output in a way that does not incorrectly concatenate multiple JSON objects into one parse attempt.
Actual Behavior
parse_json_markdown() currently anchors from the first { / [ to the last } / ] in the entire model response. If the response contains two JSON objects (or JSON plus another JSON-like block), json.loads() receives both and raises Extra data.
This can cause a Question Classifier workflow execution to fail even when the model produced a valid first JSON object.
Relevant implementation
Current api/libs/json_in_md_parser.py does roughly:
start_candidates = [i for i in (json_string.find("{"), json_string.find("[")) if i != -1]
start_index = min(start_candidates)
end_index = max(json_string.rfind("}"), json_string.rfind("]"))
extracted_content = json_string[start_index:end_index + 1].strip()
return json.loads(extracted_content)
The rfind() end selection is the problematic part when more than one JSON value is present.
Suggested fix
Use json.JSONDecoder().raw_decode() starting at the first JSON token and consume only the first complete JSON value, instead of slicing through the last closing bracket in the whole response.
For example, conceptually:
decoder = json.JSONDecoder()
obj, end = decoder.raw_decode(json_string[start_index:])
return obj
The exact implementation should preserve the existing fenced-content fallback behavior and expected-key validation.
Additional context
- Reproduced under low concurrency, so this is independent of load.
- The failure position varies across runs, consistent with varying model output shape rather than a fixed input-specific problem.
- Structured output is not available for this Question Classifier path in the observed version, so the parser should be robust to ordinary model output variation.
- No customer-specific data is required to reproduce this issue; the two-object example above reproduces the parser behavior directly.
- 主要言語
- TypeScript
- スター
- 157k
- フォーク
- 24.7k
- 平均マージ
- 22時間 32分
- マージ済み PR(30日)
- 611
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
langgenius/dify のほかの issue
-
Annotation Reply: a stored score threshold of 0.0 is silently replaced with 1, disabling the feature オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
langgenius/dify#42639 · コメント 1 件 · リアクション 1 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
langgenius/dify#42468 · コメント 1 件 · リアクション 1 件 ·
-
🐞 bug
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
langgenius/dify#42446 · リアクション 1 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
langgenius/dify#42355 · コメント 1 件 · リアクション 1 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
langgenius/dify#42350 · コメント 1 件 · リアクション 1 件 ·
langgenius/dify の issue をすべて見る
似ている issue
-
calcite-components needs triage refactor
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
Esri/calcite-design-system#15203 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
難易度 1/5 1時間未満 初心者へのやさしさ 95/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
Automattic/studio#4908 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 90/100