jd-opensource/joyagent-jdgenie · error · RuntimeError

[filter column] 多次重试后执行失败, error_msg

Error message

[filter column] {request_id} 多次重试后执行失败, error_msg:{error_msg}

What it means

_filter_single_table raises RuntimeError after exhausting all retries when LLM-based column filtering never produced a parseable result. error_msg holds the last failure's LLM response and exception, so the root cause is usually error 102 (unparseable JSON) repeated on every retry.

Solutions

  1. Inspect error_msg in the message: if it is a format issue fix the prompt/parser (see 解析llm json结果失败); if a network issue fix connectivity/rate limits
  2. Increase the retry count and add exponential backoff between attempts
  3. Validate/repair the LLM response between retries (strip fences, retry only the failing table)
  4. Reduce concurrency (semaphore) or request size if the endpoint is rate-limiting under batch load

Example fix

// before
for retry in range(max_retries):
    try:
        return parse(llm_call(...))
    except Exception as e:
        error_msg = f"..."
        continue
raise RuntimeError(f"[filter column] {request_id} 多次重试后执行失败, error_msg:{error_msg}")
// after
for retry in range(max_retries):
    try:
        return parse(llm_call(...))
    except Exception as e:
        error_msg = f"..."
        await asyncio.sleep(2 ** retry)
        continue
logger.error(f"[filter column] {request_id} final failure: {error_msg}")
raise RuntimeError(f"[filter column] {request_id} 多次重试后执行失败, error_msg:{error_msg}")
Defensive patterns

Strategy: retry

Validate before calling

# before batching, smoke-test one table
sample = await _filter_single_table(sem, table_schema_lists[0])
if sample is None:
    raise RuntimeError('column filter pipeline unhealthy; fix prompt/endpoint before batching')

Try / catch

try:
    result = await batch_get_result(request)
except RuntimeError as e:
    if '多次重试后执行失败' in str(e):
        save_partial_results_and_alert(request, str(e))

Prevention

When it happens

Trigger: All retry attempts inside _filter_single_table fail (each attempt's exception is logged and the loop continues); after the final attempt the last error_msg is wrapped and raised. Called by batch_get_stage_result and batch_get_result.

Common situations: Persistent LLM output-format drift across retries; LLM endpoint timeouts or 429/5xx errors on every attempt; retry count too low for a flaky endpoint; prompt consistently yields non-JSON answers.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08). Data as JSON: /api/errors/430c5883eed1fa45. Report an issue: GitHub.

Appendix: source

Thrown at genie-tool/genie_tool/tool/table_rag/table_column_filter.py:263

                            column_index = column_info.get("columnIndex", "")
                            default_recall = column_info.get("defaultRecall", 0)
                            
                            if column_index in result_column_indexes or default_recall == 1:
                                filter_columns.append(column_info)
                        
                        table_schema_info["schemaList"] = filter_columns
                        return table_schema_info
                    else:
                        return None
                
                except Exception as e:
                    error_msg = f"第{retry + 1}次执行结果:\n{llm_response},报错信息:{e}"
                    
                    traceback.print_exc()
                    logger.error(f"[filter column] {request_id}, fail to filter columns error_msg {error_msg}")
                    continue
            
            raise RuntimeError(f"[filter column] {request_id} 多次重试后执行失败, error_msg:{error_msg}")
    
    async def batch_get_stage_result(self):
        # table_schema_lists = self.body.get("schema_info", [])
        table_schema_lists = self.column_info
        
        if not table_schema_lists:
            return []
        
        # 第一阶段:批处理过滤(粗筛)
        batch_size = self.table_filter_batch_size  # 增大 batch 提高吞吐
        semaphore1 = asyncio.Semaphore(self.table_filter_batch_size)
        
        # 流式生成 batch
        def batch_generator():
            for i in range(0, len(table_schema_lists), batch_size):
                yield table_schema_lists[i:i + batch_size]
        
        # 异步执行所有 batch,流式获取完成结果

View on GitHub (pinned to 2417e0b8b6)