or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/io.quarkiverse.langchain4j/quarkus-langchain4j-core@1.5.x

docs

index.md
tile.json

tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-core

tessl install tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-core@1.5.0

Quarkus LangChain4j Core provides runtime integration for LangChain4j with the Quarkus framework, enabling declarative AI service creation through CDI annotations.

error-handling.mddocs/reference/

Error Handling

Error Handling provides custom error handlers for tool argument parsing and execution errors, enabling graceful degradation and retry logic.

Capabilities

@HandleToolArgumentError Annotation

Marks a static method as a handler for tool argument parsing errors.

// Package: io.quarkiverse.langchain4j
/**
 * Annotation for handling tool argument parsing errors.
 * Place on a static method that handles ToolArgumentsException.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HandleToolArgumentError {
}

Method Signature Requirements:

  • Must be static
  • Can accept: Throwable, ToolErrorContext, or both
  • Must return: String or ToolErrorHandlerResult

Usage Example:

import io.quarkiverse.langchain4j.HandleToolArgumentError;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolErrorContext;

public class DataTool {

    @Tool("Process data with parameters")
    public String processData(String format, int count, boolean verbose) {
        // Tool implementation
        return "Processed";
    }

    @HandleToolArgumentError
    public static String handleArgumentError(Throwable error, ToolErrorContext context) {
        return "Invalid arguments provided: " + error.getMessage() +
               ". Expected: format (string), count (integer), verbose (boolean)";
    }
}

@HandleToolExecutionError Annotation

Marks a static method as a handler for tool execution errors.

// Package: io.quarkiverse.langchain4j
/**
 * Annotation for handling tool execution errors.
 * Place on a static method that handles ToolExecutionException.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HandleToolExecutionError {
}

Method Signature Requirements:

  • Must be static
  • Can accept: Throwable, ToolErrorContext, or both
  • Must return: String or ToolErrorHandlerResult

Usage Example:

import io.quarkiverse.langchain4j.HandleToolExecutionError;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolErrorContext;
import java.sql.SQLException;

public class DatabaseTool {

    @Tool("Query database")
    public String query(String sql) {
        try {
            return executeQuery(sql);
        } catch (SQLException e) {
            throw new RuntimeException("Database error", e);
        }
    }

    @HandleToolExecutionError
    public static String handleExecutionError(Throwable error, ToolErrorContext context) {
        if (error.getCause() instanceof SQLException) {
            return "Database is temporarily unavailable. Please try again later.";
        }
        return "An error occurred while querying the database: " + error.getMessage();
    }

    private String executeQuery(String sql) throws SQLException {
        // Database query implementation
        return "result";
    }
}

Error Handler Examples

Simple Error Handler

import io.quarkiverse.langchain4j.HandleToolArgumentError;

@HandleToolArgumentError
public static String handleArgumentError(Throwable error) {
    return "Invalid tool arguments: " + error.getMessage();
}

Context-Aware Error Handler

import io.quarkiverse.langchain4j.HandleToolExecutionError;
import dev.langchain4j.agent.tool.ToolErrorContext;

@HandleToolExecutionError
public static String handleExecutionError(Throwable error, ToolErrorContext context) {
    String toolName = context.toolSpecification().name();
    String args = context.toolExecutionRequest().arguments();

    return String.format(
        "Tool '%s' failed with arguments %s. Error: %s",
        toolName, args, error.getMessage()
    );
}

Retry Logic Error Handler

import io.quarkiverse.langchain4j.HandleToolExecutionError;
import dev.langchain4j.agent.tool.ToolErrorContext;
import dev.langchain4j.agent.tool.ToolErrorHandlerResult;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

@HandleToolExecutionError
public static ToolErrorHandlerResult handleExecutionError(
    Throwable error,
    ToolErrorContext context
) {
    if (isRetryable(error)) {
        return ToolErrorHandlerResult.retry(
            "Operation failed, retrying...",
            3  // max retries
        );
    } else {
        return ToolErrorHandlerResult.failure(
            "Operation failed permanently: " + error.getMessage()
        );
    }
}

private static boolean isRetryable(Throwable error) {
    return error instanceof TimeoutException ||
           error instanceof IOException;
}

Fallback Error Handler

import io.quarkiverse.langchain4j.HandleToolExecutionError;
import dev.langchain4j.agent.tool.ToolErrorContext;
import java.util.concurrent.TimeoutException;

@HandleToolExecutionError
public static String handleExecutionError(Throwable error, ToolErrorContext context) {
    // Log error for monitoring
    logError(context.toolSpecification().name(), error);

    // Provide fallback response
    if (error instanceof TimeoutException) {
        return "Request timed out. Using cached data from last successful request.";
    } else if (error instanceof NetworkException) {
        return "Network unavailable. Operating in offline mode.";
    }

    return "Service temporarily unavailable. Using default values.";
}

private static void logError(String toolName, Throwable error) {
    // Logging implementation
}

Exception Types

PreventsErrorHandlerExecution Interface

Marker interface for exceptions that bypass error handlers.

// Package: io.quarkiverse.langchain4j.runtime
/**
 * Marker interface for exceptions that prevent error handler execution.
 * Exceptions implementing this interface immediately terminate execution
 * without invoking error handlers.
 */
public interface PreventsErrorHandlerExecution {
}

BlockingToolNotAllowedException

Exception thrown when a blocking tool is called on the Vert.x event loop.

// Package: io.quarkiverse.langchain4j.runtime
/**
 * Exception thrown when blocking tool call attempted on event loop.
 * Implements PreventsErrorHandlerExecution to bypass error handlers.
 */
public class BlockingToolNotAllowedException
    extends RuntimeException
    implements PreventsErrorHandlerExecution {

    /**
     * Create exception with message.
     *
     * @param message Error message
     */
    public BlockingToolNotAllowedException(String message);
}

Example:

import dev.langchain4j.agent.tool.Tool;

public class BlockingTool {

    @Tool("Perform blocking I/O")
    public String blockingOperation(String input) {
        // This will throw BlockingToolNotAllowedException if called on event loop
        try {
            Thread.sleep(1000);  // Blocking operation
            return "Done";
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

Error Handler Return Types

String Return Type

Simple error message returned to the LLM:

import io.quarkiverse.langchain4j.HandleToolExecutionError;

@HandleToolExecutionError
public static String handleError(Throwable error) {
    return "Error: " + error.getMessage();
}

ToolErrorHandlerResult Return Type

Structured result with more control:

import io.quarkiverse.langchain4j.HandleToolExecutionError;
import dev.langchain4j.agent.tool.ToolErrorHandlerResult;

@HandleToolExecutionError
public static ToolErrorHandlerResult handleError(Throwable error) {
    if (isRetryable(error)) {
        return ToolErrorHandlerResult.retry("Retrying...", 3);
    } else if (isFatal(error)) {
        return ToolErrorHandlerResult.fatal("Fatal error", error);
    } else {
        return ToolErrorHandlerResult.failure("Temporary error");
    }
}

Best Practices

Error Handler Design

  1. Be Specific: Provide clear, actionable error messages
  2. Include Context: Use ToolErrorContext to provide relevant details
  3. Categorize Errors: Distinguish between retryable and permanent failures
  4. User-Friendly: Return messages the LLM can understand and act on
  5. Log Details: Log technical details while returning user-friendly messages

Example: Comprehensive Error Handler

import io.quarkiverse.langchain4j.HandleToolExecutionError;
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolErrorContext;
import org.jboss.logging.Logger;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class RobustTool {

    private static final Logger LOG = Logger.getLogger(RobustTool.class);

    @Tool("Robust operation")
    public String execute(String param) {
        // Tool implementation
        return "result";
    }

    @HandleToolExecutionError
    public static String handleExecutionError(Throwable error, ToolErrorContext context) {
        String toolName = context.toolSpecification().name();
        String args = context.toolExecutionRequest().arguments();

        // Log technical details
        LOG.errorf(error, "Tool '%s' failed with arguments: %s", toolName, args);

        // Categorize and respond appropriately
        if (error instanceof TimeoutException) {
            return "The operation timed out. This usually indicates the service is busy. " +
                   "Try again in a few moments.";
        } else if (error instanceof IllegalArgumentException) {
            return "Invalid parameters provided. " + error.getMessage();
        } else if (error instanceof SecurityException) {
            return "Access denied. You don't have permission to perform this operation.";
        } else if (error instanceof IOException) {
            return "Network or I/O error occurred. The service may be temporarily unavailable.";
        }

        // Generic fallback
        return "An unexpected error occurred. The operation could not be completed.";
    }
}

Use Cases

Error handling is useful for:

  • Graceful Degradation: Continue operation despite errors
  • User-Friendly Messages: Convert technical errors to understandable messages
  • Retry Logic: Automatically retry transient failures
  • Fallback Strategies: Provide alternative responses when tools fail
  • Error Logging: Centralize error logging and monitoring
  • Context-Aware Responses: Tailor error messages based on context
  • Error Classification: Distinguish between user errors and system errors
  • Circuit Breaker: Implement circuit breaker patterns in error handlers