How to Implement Custom Error Code Handlers Using LinkisErrorCode Interfaces for Engine-Specific Exceptions

To implement custom error code handlers for engine-specific exceptions in Apache Linkis, create an enum implementing LinkisErrorCode, then implement the ExceptionErrorCodeHandler interface to map engine exceptions to those codes, and register the handler via the LinkisErrorCodeFactory or direct instantiation.

Apache Linkis provides a pluggable error code framework that standardizes how engine exceptions are reported across the platform. By implementing the LinkisErrorCode interface and creating custom ExceptionErrorCodeHandler implementations, you can map engine-specific failures to structured error codes that integrate seamlessly with Linkis's error handling infrastructure.

Understanding the Linkis Error Code Architecture

The framework centers on three core interfaces defined in linkis-pes-client. The base ErrorCodeHandler interface provides the foundational contract, while ExceptionErrorCodeHandler specifically targets engine-specific Throwable objects. The default implementation, LinkisErrorCodeHandler, aggregates multiple handler types but contains a stub handle(Throwable) method that returns null at lines 22-25, necessitating custom implementations for exception-based error mapping.

Key source files include:

Step 1: Define Engine-Specific Error Codes

Create an enum implementing org.apache.linkis.common.errorcode.LinkisErrorCode to define your engine's error code taxonomy. This mirrors existing implementations like EngineconnCoreErrorCodeSummary found in linkis-computation-governance/linkis-engineconn/linkis-engineconn-plugin-core/src/main/java/org/apache/linkis/manager/engineplugin/errorcode/EngineconnCoreErrorCodeSummary.java.

package org.apache.linkis.myengine.errorcode;

import org.apache.linkis.common.errorcode.LinkisErrorCode;

public enum MyEngineErrorCode implements LinkisErrorCode {
    ENGINE_START_FAILURE(20001, "Failed to start MyEngine instance"),
    ENGINE_TIMEOUT(20002, "MyEngine execution timed out after {0} ms"),
    INVALID_QUERY_SYNTAX(20003, "Query syntax error: {0}");

    private final int errorCode;
    private final String errorDesc;

    MyEngineErrorCode(int errorCode, String errorDesc) {
        this.errorCode = errorCode;
        this.errorDesc = errorDesc;
    }

    @Override
    public int getErrorCode() { return errorCode; }

    @Override
    public String getErrorDesc() { return errorDesc; }
}

Step 2: Implement the ExceptionErrorCodeHandler Interface

Create a handler class that implements ExceptionErrorCodeHandler and overrides the handle(Throwable t) method. This method inspects exception types and returns the appropriate LinkisErrorCode enum value, or null to allow fallback to other handlers.

package org.apache.linkis.myengine.errorhandler;

import org.apache.linkis.errorcode.client.handler.ExceptionErrorCodeHandler;
import org.apache.linkis.myengine.errorcode.MyEngineErrorCode;
import org.apache.linkis.myengine.exception.MyEngineException;
import org.apache.linkis.common.errorcode.LinkisErrorCode;

public class MyEngineExceptionHandler implements ExceptionErrorCodeHandler {

    @Override
    public LinkisErrorCode handle(Throwable t) {
        if (t instanceof MyEngineException) {
            String msg = t.getMessage();
            if (msg != null && msg.contains("timeout")) {
                return MyEngineErrorCode.ENGINE_TIMEOUT;
            } else if (msg != null && msg.contains("syntax")) {
                return MyEngineErrorCode.INVALID_QUERY_SYNTAX;
            } else {
                return MyEngineErrorCode.ENGINE_START_FAILURE;
            }
        }
        // Fallback – let the default handler deal with it
        return null;
    }
}

Step 3: Register and Wire the Custom Handler

You can integrate your handler either by replacing the factory singleton or through direct instantiation.

Option A: Replace the Factory Handler

Subclass LinkisErrorCodeHandler to create a composite that delegates to your custom handler first, then falls back to the default logic:

import org.apache.linkis.errorcode.client.handler.LinkisErrorCodeHandler;
import org.apache.linkis.myengine.errorhandler.MyEngineExceptionHandler;

LinkisErrorCodeHandler customHandler = new LinkisErrorCodeHandler() {
    private final MyEngineExceptionHandler engineHandler = new MyEngineExceptionHandler();

    @Override
    public LinkisErrorCode handle(Throwable t) {
        LinkisErrorCode code = engineHandler.handle(t);
        return code != null ? code : super.handle(t);
    }
};

Option B: Direct Usage

Instantiate and invoke the handler directly within your engine execution logic:

MyEngineExceptionHandler handler = new MyEngineExceptionHandler();

try {
    // engine execution logic
} catch (Throwable e) {
    LinkisErrorCode code = handler.handle(e);
    if (code != null) {
        // process specific error code
    } else {
        // generic fallback handling
    }
}

Step 4: Integrate with Engine Execution

In your engine's execution driver, catch exceptions and delegate to the custom handler to translate them into structured error codes consumable by the Linkis UI or REST API.

public class MyEngineExecutor {
    private final MyEngineExceptionHandler errHandler = new MyEngineExceptionHandler();

    public void execute(String sql) {
        try {
            // actual engine execution logic
        } catch (Throwable t) {
            LinkisErrorCode code = errHandler.handle(t);
            if (code != null) {
                System.out.println("Engine error: " + code.getErrorCode() + " - " + code.getErrorDesc());
            } else {
                System.out.println("Unknown error: " + t.getMessage());
            }
        }
    }
}

Key Source Files for Reference

Summary

  • Define engine-specific error codes by creating an enum implementing LinkisErrorCode.
  • Implement the ExceptionErrorCodeHandler interface to translate engine exceptions into structured error codes.
  • Register your handler by subclassing LinkisErrorCodeHandler or using direct instantiation in the execution path.
  • Return null from your handler for unrecognized exceptions to enable fallback to default handlers.
  • Integrate the handler in your engine's execution driver to map failures to standardized error responses.

Frequently Asked Questions

What is the difference between ExceptionErrorCodeHandler and LogErrorCodeHandler?

ExceptionErrorCodeHandler processes Java Throwable objects directly at runtime, making it suitable for engine-specific exception mapping. LogErrorCodeHandler and LogFileErrorCodeHandler parse string log output or log files to extract error codes using pattern matching, which is useful for post-hoc analysis of engine logs.

Why does the default LinkisErrorCodeHandler return null for exceptions?

The default LinkisErrorCodeHandler.handle(Throwable) method is implemented as a stub returning null in LinkisErrorCodeHandler.java at lines 22-25. This design forces developers to implement custom ExceptionErrorCodeHandler classes for engine-specific error mapping while preserving the existing log-parsing functionality.

Can I use multiple ExceptionErrorCodeHandler implementations?

Yes. You can chain multiple handlers by checking for null return values and delegating to the next handler in sequence. When subclassing LinkisErrorCodeHandler, call super.handle(t) after your custom logic to maintain fallback to the default log-based error detection.

How do I expose error codes through the Linkis REST API?

Use LinkisErrorCodeClient built via ErrorCodeClientBuilder to send mapped error codes to the Linkis error-code REST API. After obtaining an ErrorCode from your handler, instantiate the client and call getErrorCodeByCode() to retrieve detailed error information for client responses.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →