jd-opensource/joyagent-jdgenie · error · IllegalStateException

Tool execution failed: " + error

Error message

Tool execution failed: " + error

What it means

ToolResult.getResultOrThrow throws IllegalStateException when the tool execution completed but isSuccess() is false, meaning the tool reported a failure via its error field. The message embeds the underlying tool error string so callers can see why the tool failed.

Solutions

  1. Check isSuccess() before calling getResultOrThrow and handle the failure path
  2. Log ToolResult.getError() to find the root cause of the tool failure
  3. Fix the underlying tool invocation that produced the error

Example fix

// before
T result = toolResult.getResultOrThrow(MyResult.class);
// after
if (!toolResult.isSuccess()) {
    log.warn("tool failed: {}", toolResult.getError());
    return fallbackResult();
}
T result = toolResult.getResultOrThrow(MyResult.class);
Defensive patterns

Strategy: try-catch

Validate before calling

if (toolResult == null || !toolResult.isSuccess()) { /* take failure path */ }

Type guard

boolean usable(ToolResult r) { return r != null && r.isSuccess() && r.getResult() != null; }

Try / catch

try {
    T r = toolResult.getResultOrThrow(T.class);
} catch (IllegalStateException e) {
    log.warn("tool failed: {}", toolResult.getError());
    return fallback;
}

Prevention

When it happens

Trigger: Calling getResultOrThrow/getResultOrDefault on a ToolResult where the execution failed and the error field is non-null.

Common situations: Tool execution threw internally, the tool returned an error response from an external API, or a timeout/parse failure set the error field before the agent reads the result.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at genie-backend/src/main/java/com/jd/genie/agent/dto/tool/ToolResult.java:154

     * 检查是否被取消
     */
    public boolean isCancelled() {
        return status == ExecutionStatus.CANCELLED;
    }

    /**
     * 检查是否被跳过
     */
    public boolean isSkipped() {
        return status == ExecutionStatus.SKIPPED;
    }

    /**
     * 获取结果或抛出异常
     */
    public <T> T getResultOrThrow(Class<T> resultType) {
        if (!isSuccess()) {
            throw new IllegalStateException("Tool execution failed: " + error);
        }

        if (result == null) {
            throw new IllegalStateException("Tool execution result is null");
        }

        if (!resultType.isInstance(result)) {
            throw new ClassCastException("Result is not of type " + resultType.getName());
        }

        return resultType.cast(result);
    }

    /**
     * 获取结果或返回默认值
     */
    public <T> T getResultOrDefault(Class<T> resultType, T defaultValue) {
        try {

View on GitHub (pinned to 2417e0b8b6)