bug: Three reproducible bugs: None-content crash, negative max_tokens, stale image error handling
Three reproducible bugs found while running self-referential simulations (MiroFish analyzing its own launch/reception)
Setup: Local Docker deployment (ghcr.io/666ghj/mirofish:latest), LLM backend = openai/gpt-oss-20b via NVIDIA API (OpenAI-SDK-compatible endpoint), Zep Cloud free tier for memory.
Bug 1: LLMClient.chat() crashes on content=None from reasoning models
Error:
报告生成失败: expected string or bytes-like object, got 'NoneType'
When it happens: Deterministically during Step 4/5 (report generation), right after the SECTION START log of the first outline section (reproduced on two independent runs, different seeds/outlines, identical failure point).
Root cause (verified in shipped image code, backend/app/utils/llm_client.py, chat()):
content = response.choices[0].message.content
content = re.sub(r'<think>[\s\S]*?</think>', '', content).strip()
Reasoning models served through OpenAI-compatible endpoints (observed: gpt-oss-20b via NVIDIA) sometimes return the output in reasoning_content with message.content = None. re.sub() on None raises the TypeError above. There is no None guard anywhere on this path.
Suggested fix: Fall back to reasoning_content when content is None (verified working locally):
content = message.content
if content is None:
content = getattr(message, 'reasoning_content', None) or ''
Impact: Affects any reasoning model on this code path, regardless of provider.
Bug 2: Unclamped token budget goes negative on long simulations (observed, exact computation site unverified)
Error (from simulation.log):
openai.BadRequestError: Error code: 400 - {'error': {... 'max_tokens must be at least 1, got -365748' ...}}
When it happens: Round 94/120 of a long run, as accumulated context grows. (Hypothesis, not yet traced to a line: budget computed as context-window minus prompt size with no lower-bound clamp. The 400 and the negative value are confirmed from logs; the exact computation site still needs tracing — likely in the simulation runner or OASIS layer.)
Suggested fix: Clamp to a sane minimum before the API call and/or truncate/summarize history near the context limit.
Impact: Any sufficiently long run will eventually fail mid-run on any provider.
Bug 3: Shipped Docker image lags main — dead models surface as generic 500
Observations (both verified):
openai/gpt-oss-120breturns410 Goneon NVIDIA ("has reached its end of life on 2026-09-03") — any config pointing at it fails.- The shipped image's
backend/app/api/graph.pyhas no provider-error branches (no502/LLMResponseErrorhandling), while current GitHubmaindoes. So provider failures (410, 429, 400…) surface to the user as a generic500, with no actionable message and no traceback in eitherdocker logsor the in-container log file (theexceptblock logs onlystr(e)).
Suggested fix: Rebuild/pin the image closer to main, and backport the 502-with-provider-status error mapping so dead keys/models/quotas produce diagnosable errors instead of 500.
Additional context (non-bug finding): seed wording drives ontology reification
A/B on seed design, same tool + model: seed naming concrete products → ontology collapsed to 2 agents (the named entities), ~19 events/40 rounds. Same content rewritten with social roles instead of proper nouns → 21 entities, 8 role-based agents, 168 events before Bug 2 hit (~9x activity). Worth a note in seed-writing docs.
Happy to share the two seed files and simulation IDs (sim_428bbb515066, sim_f29e23670506)
Source: 666ghj/MiroFish