ZhuLinsen/daily_stock_analysis · error · CodexAppServerError
capability_unsupported
capability_unsupported
Error message
No cancellation-safe DSA tools are available to Codex
What it means
Raised by CodexAgentBackend right before spawning a Codex App Server thread when ToolSurface.list_tools('public', cancellation_safe_only=True) returns an empty list. The Codex integration only exposes tools whose ToolPolicy.cancellation_safe flag is True, because a user cancellation must be able to interrupt the turn safely. If the registry is empty or every registered tool is marked cancellation-unsafe, the backend refuses to start the session with code 'capability_unsupported'.
Source
Thrown at src/agent/codex_agent_backend.py:152
command,
tool_surface=self.tool_surface,
tool_context=tool_context,
request_timeout=remaining_timeout(),
tool_event_callback=on_tool_event,
deadline=deadline,
cancel_event=request.cancel_event,
max_tool_calls=request.max_steps,
) as client:
client.request_timeout = remaining_timeout()
tool_names = [
item["name"]
for item in self.tool_surface.list_tools(
"public",
cancellation_safe_only=True,
)
]
if not tool_names:
raise CodexAppServerError(
"capability_unsupported",
"No cancellation-safe DSA tools are available to Codex",
)
developer_instructions = request.system_prompt
if request.stock_scope is None:
developer_instructions = (
f"{developer_instructions}\n\n{_NO_STOCK_SCOPE_INSTRUCTION}"
)
thread_id = client.start_thread(
tool_names=tool_names,
base_instructions=_BASE_INSTRUCTIONS,
developer_instructions=developer_instructions,
)
client.request_timeout = remaining_timeout()
isolation = client.inspect_external_tool_isolation(thread_id)
if not isolation.get("passed"):
raise CodexAppServerError(
"capability_unsupported",View on GitHub (pinned to 5159bd72e8)
Solutions
- Register at least one tool whose ToolPolicy sets cancellation_safe=True before invoking the Codex backend
- Inspect the registry at startup: assert tool_surface.list_tools('public', cancellation_safe_only=True) is non-empty and fail fast with a clear provisioning error
- If you constructed ToolSurface.empty(), replace it with ToolSurface(registry) built from your real ToolRegistry
- Audit recent changes to tool policy definitions to see whether cancellation_safe was inadvertently flipped to False
Example fix
// before
surface = ToolSurface.empty() # protocol-only, no tools registered
backend = CodexAgentBackend(tool_surface=surface)
await backend.run(request) # raises capability_unsupported
// after
registry = build_default_registry() # registers DSA tools
surface = ToolSurface(registry)
if not surface.list_tools('public', cancellation_safe_only=True):
raise RuntimeError('no cancellation-safe tools registered; check tool policies')
backend = CodexAgentBackend(tool_surface=surface) Defensive patterns
Strategy: validation
Validate before calling
safe = surface.list_tools("public", cancellation_safe_only=True)
if not safe:
raise ProvisioningError(
"no cancellation-safe tools registered; register tools with "
"ToolPolicy(cancellation_safe=True) before starting the Codex backend"
)
backend = CodexAgentBackend(tool_surface=surface) Type guard
def has_cancellation_safe_tools(surface: ToolSurface) -> bool:
return bool(surface.list_tools("public", cancellation_safe_only=True)) Try / catch
try:
await backend.run(request)
except CodexAppServerError as exc:
if exc.code == "capability_unsupported":
fail_fast("tool provisioning defect: " + str(exc))
raise Prevention
- Add a startup assertion that the registry contains at least one cancellation-safe tool
- Never wire ToolSurface.empty() into a production backend; reserve it for protocol preflight tests
- Cover tool policies with unit tests so cancellation_safe flags cannot silently regress
When it happens
Trigger: Calling the Codex agent backend when the ToolRegistry contains no tools, or when every ToolDefinition has policy.cancellation_safe=False; also triggered when ToolSurface.empty() (the Phase 6a protocol-only surface backed by an empty ToolRegistry) is wired into a production backend instead of a populated registry.
Common situations: A new deployment forgets to run tool registration at startup; a refactor removes the only cancellation-safe tool; a test harness uses ToolSurface.empty() outside preflight tests; policy defaults were changed so tools default to cancellation_safe=False.
Related errors
- tool_not_found
- [AlphaVantage] API key not configured
- {market_label} {stock_code} 获取失败: 暂无可用数据源
- 无法确定 ETF {stock_code} 的 Eastmoney 市场前缀
- [Finnhub] API key not configured
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/edd5d3012904b05e.
Report an issue: GitHub.