NEW

Chainlink Data Streams have officially launched on mainnet. Sign up for early access.

Back

Using the StreamsLookup error handler

The Chainlink Automation StreamsLookup error handler provides insight into potential errors or edge cases in StreamsLookup upkeeps. The table below outlines a range of error codes and the behavior associated with the codes. Use the checkErrorHandler function to specify how you want to respond to the error codes. checkErrorHandler is simulated offchain and determines what action for Automation to take onchain in performUpkeep.

Error handler

When Automation detects an event, it runs the checkLog function, which includes a StreamsLookup revert custom error. If this StreamsLookup error triggers, and the call to pull a report from Data Streams is unsuccessful, the checkErrorHandler function runs offchain and determines what action Automation takes onchain in performUpkeep. The upkeep runs the custom logic you define in your checkErrorHandler function to handle report request errors. If the call to pull a report is successful, the checkCallback function is simulated offchain. Both functions have the same output types (bool upkeepNeeded, bytes memory performData), which Automation uses to run performUpkeep onchain.

Error handler flow diagram

Add the checkErrorHandler function in your contract to specify how you want to handle error codes:

function checkErrorHandler(uint errorCode, bytes extraData) external pure returns (bool upkeepNeeded, bytes memory performData) {
   // custom logic to handle error codes
}

Testing checkErrorHandler

checkErrorHandler is simulated offchain. When upkeepNeeded returns true, Automation runs performUpkeep onchain using the performData from checkErrorHandler. If the checkErrorHandler function itself reverts, performUpkeep does not run.

If you need to force errors in streamsLookup while testing, you can try the following methods:

  • Specifying an incorrect feedID to force error code 800400 (ErrCodeStreamsBadRequest)
  • Specifying a future timestamp to force error code 808206 (where partial content is received) for both single feedID and bulk feedID requests
  • Specifying old timestamps for reports not available anymore yields either error code 808504 (no response) or 808600 (bad response), depending on which service calls the timeout request

If your StreamsLookup revert function is defined incorrectly in your smart contracts, the nodes will not be able to decode it.

Error codes

Error codeRetriesPossible cause of errorData Streams equivalent API response
No errorN/ANo error200 (Status OK)
ErrCodeStreamsBadRequest: 800400NoUser requested 0 feedsN/A
User error, incorrect parameter input400 (StatusBadRequest)
Issue with encoding http url (bad characters)N/A
ErrCodeStreamsUnauthorized: 808401NoKey access issue or incorrect feedID401 (StatusUnauthorized)
808206Log trigger - after retries; Conditional immediatelyRequested m reports but only received n (partial)200 (Status OK) or StatusPartialContent
8085XX (e.g 808500)Log trigger - after retries; Conditional immediatelyNo response
  • 500 (StatusInternalServerError)
  • 502 (StatusBadGateway)
  • 503 (StatusServiceUnavailable)
  • 504 (StatusGatewayTimeout)
ErrCodeStreamsBadResponse: 808600NoError in reading body of returned response, but service is up200 but can't decode Data Streams output
ErrCodeStreamsTimeout: 808601NoNo valid report is received for 10 seconds (e.g. Data Streams returns 200 but no report)No valid Data Streams report received within 10 seconds (200 but no report)
ErrCodeStreamsUnknownError: 808700NoUnknownAnything else

Example code

This example code highlights the revert StreamsLookup, checkCallback, checkErrorHandler and performUpkeep functions. The full code example is available here.

...
function checkLog(Log calldata log, bytes memory)
    external
    returns (bool upkeepNeeded, bytes memory performData)
{
    revert StreamsLookup(
        STRING_DATASTREAMS_FEEDLABEL,
        feedIds,
        STRING_DATASTREAMS_QUERYLABEL,
        log.timestamp,
        ""
    );
}

function checkCallback(bytes[] calldata values, bytes calldata extraData)
    external
    pure
    returns (bool, bytes memory)
{
    bool success = true;
    return (true, abi.encode(values, extraData, success));
}

function checkErrorHandler(
    bytes calldata errorCode,
    bytes calldata extraData
) public view returns (bool upkeepNeeded, bytes memory performData) {
    bool success = false;
    // catch error and handle
    return (true, abi.encode(errorCode, extraData, success));
}

// function will be performed on-chain
function performUpkeep(bytes calldata performData) external {
    // Decode incoming performData
    (
        bytes[] memory signedReports,
        bytes memory extraData,
        bool reportSuccess
    ) = abi.decode(performData, (bytes[], bytes, bool));

    if (reportSuccess) {
        bytes memory report = signedReports[0];

        (, bytes memory reportData) = abi.decode(
        ...

What's next

Stay updated on the latest Chainlink news