tessl install tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-core@1.5.0Quarkus LangChain4j Core provides runtime integration for LangChain4j with the Quarkus framework, enabling declarative AI service creation through CDI annotations.
Error Handling provides custom error handlers for tool argument parsing and execution errors, enabling graceful degradation and retry logic.
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:
Throwable, ToolErrorContext, or bothString or ToolErrorHandlerResultUsage 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)";
}
}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:
Throwable, ToolErrorContext, or bothString or ToolErrorHandlerResultUsage 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";
}
}import io.quarkiverse.langchain4j.HandleToolArgumentError;
@HandleToolArgumentError
public static String handleArgumentError(Throwable error) {
return "Invalid tool arguments: " + error.getMessage();
}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()
);
}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;
}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
}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 {
}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);
}
}
}Simple error message returned to the LLM:
import io.quarkiverse.langchain4j.HandleToolExecutionError;
@HandleToolExecutionError
public static String handleError(Throwable error) {
return "Error: " + error.getMessage();
}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");
}
}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.";
}
}Error handling is useful for: