sansan0/TrendRadar · error · FileParseError
FILE_PARSE_ERROR
FILE_PARSE_ERROR
Error message
解析文件 {config_path} 失败: 配置文件不存在 What it means
Raised inside RSSParser._parse_json_feed when the content was detected as a JSON Feed (by _is_json_feed) but json.loads fails. Note the detection only sniffs JSON shape, so content that looks JSON-ish (starts like an object) yet contains syntax errors reaches this decoder and raises ValueError wrapping the JSONDecodeError with position info.
Source
Thrown at mcp_server/services/parser_service.py:367
"""
解析YAML配置文件
Args:
config_path: 配置文件路径,默认为 config/config.yaml
Returns:
配置字典
Raises:
FileParseError: 配置文件解析错误
"""
if config_path is None:
config_path = self.project_root / "config" / "config.yaml"
else:
config_path = Path(config_path)
if not config_path.exists():
raise FileParseError(str(config_path), "配置文件不存在")
try:
with open(config_path, "r", encoding="utf-8") as f:
config_data = yaml.safe_load(f)
return config_data
except Exception as e:
raise FileParseError(str(config_path), str(e))
def parse_frequency_words(self, words_file: str = None) -> List[Dict]:
"""
解析关键词配置文件(带 mtime 缓存)
仅当 frequency_words.txt 被修改时才重新解析,避免循环内重复 IO。
复用 trendradar.core.frequency 的解析逻辑,支持:
- # 开头的注释行
- 空行分隔词组
- [组别名] 作为词组第一行,给整组指定别名View on GitHub (pinned to 8ee26026ba)
Solutions
- Read the wrapped JSONDecodeError position from the message and inspect content around that offset — 'Expecting value' at line 1 col 1 usually means BOM/HTML, mid-string errors mean truncation.
- Strip a leading BOM before parsing: content = content.lstrip('\ufeff').
- Re-fetch the feed and check Content-Length vs len(content) to detect truncation; retry on mismatch.
- Verify the URL actually serves a JSON Feed (version_url / top-level 'version' key) and that no HTML error page is being passed in.
Example fix
# before
data = json.loads(content) # raises on BOM/truncated body
# after (defensive caller)
content = content.lstrip('\ufeff')
try:
items = parser.parse(content, feed_url)
except ValueError as e:
if len(content) < 200:
logger.warning("feed %s returned suspiciously short body", feed_url)
raise Defensive patterns
Strategy: try-catch
Validate before calling
def json_feed_probe(content: str) -> bool:
"""Verify JSON-decodability before handing to the parser."""
try:
json.loads(content.lstrip("\ufeff"))
return True
except json.JSONDecodeError:
return False Try / catch
try:
items = parser.parse(content, feed_url)
except ValueError as e:
if "JSON Feed" in str(e):
logger.warning("feed %s sent malformed JSON; refetching once", feed_url)
content = refetch(feed_url)
items = parser.parse(content, feed_url) # single retry, not a loop Prevention
- Strip a UTF-8 BOM (content.lstrip('\ufeff')) before parsing — the most common avoidable JSONDecodeError here.
- Compare received body length against Content-Length to detect truncation before parsing.
- Never hand-edit saved feed bodies with tools that smart-quote or allow trailing commas.
When it happens
Trigger: Calling parse() with content that _is_json_feed classifies as JSON but is malformed: truncated response body (cut mid-download), BOM prefixed to the body (\ufeff{...}) which json.loads rejects, single quotes / trailing commas from a hand-edited file, or content-type sniffing wrong on an HTML fragment that happens to start with '{'.
Common situations: Fetching a JSON feed over an unstable proxy that truncates the body; a server sending UTF-8-BOM; copying feed samples through tools that smart-quote characters; upstream switching from XML to JSON or vice versa so the sniffer picks the wrong branch on partially migrated endpoints.
Related errors
- DATA_NOT_FOUND
- 不支持的模式: {mode}。支持的模式: daily, current
- limit 参数必须是整数类型
- date_range JSON 解析失败: {e}
- date_range 必须是字典类型、日期字符串或有效的JSON字符串
AI-assisted analysis of sansan0/TrendRadar@8ee26026ba (2026-08-15).
Data as JSON: /api/errors/dc34d398fa89299e.
Report an issue: GitHub.