Skip to content

Query failing with "negative substring length not allowed" #55

Open

Description

@A60AB5450353F40E

If limit: 1 then it fails, if some greater number then it executes OK.
In this example even limit: 2 executes OK.

# Matches all spends from AnyHedge v0.11 contract template
# https://gitlab.com/GeneralProtocols/anyhedge/contracts/-/blob/development/contracts/v0.11/bytecode.asm
query {
  input(
    limit: 1
    offset: 0
    where: {
      transaction: {
        block_inclusions: {
          block: {
            height: { _gte: 780000, _lt: 780100 }
            accepted_by: { node: { name: { _eq: "bchn-mainnet" } } }
          }
        }
      }
      _or: [
        { unlocking_bytecode_pattern: { _eq: "40104010514d" } }
        { unlocking_bytecode_pattern: { _eq: "4141004d" } }
      ]
      redeem_bytecode_pattern: {
        _regex: "04040[2-4]0[2-4]0[2-8]0[2-8]21(17|19|23)(17|19|23)(00|51)21215c79009c637b695c7a7cad5b7a7cad6d6d6d6d6d51675c7a519dc3519d5f7a5f795779bb5d7a5d79577abb5c79587f77547f75817600a0695c79587f77547f75818c9d5c7a547f75815b799f695b795c7f77817600a0695979a35879a45c7a547f7581765c7aa2695b7aa2785a7a8b5b7aa5919b690276587a537a96a47c577a527994a4c4529d00cc7b9d00cd557a8851cc9d51cd547a8777777768"
      }
    }
  ) {
    transaction {
      block_inclusions {
        block {
          height
          timestamp
        }
      }
      inputs {
        outpoint_transaction_hash
        outpoint_index
        outpoint {
          value_satoshis
          transaction {
            block_inclusions {
              block {
                height
                timestamp
              }
            }
          }
        }
      }
    }
  }
}

Activity

  1. bitjson commented on Feb 24, 2023

    @bitjson
    Member

    Thanks for opening an issue! On the demo instance, that returns:

    {
      "errors": [
        {
          "extensions": {
            "code": "data-exception",
            "path": "$"
          },
          "message": "negative substring length not allowed"
        }
      ]
    }

    That's an error coming back from Postgres. To figure it out, we'd need to run the query in the Hasura console and use the analyze button to get the actual Postgres query being run, then figure out where the error is actually happening.

    I'd guess it's because you're filtering by redeem_bytecode_pattern, which is itself a computed property. So if the other conditions take your limit 1 query down to 0, it's running that function on nothing, and somewhere inside there it "works" until a substring function is called with a negative integer.

    I'd guess redeem_bytecode_pattern just needs to return early before doing the invalid operation. I can't prioritize figuring this out myself, but I'd be happy to take a PR!

  2. A60AB5450353F40E commented on Feb 24, 2023

    @A60AB5450353F40E
    Author

    Thing is, other conditions don't limit it to 0. For example if you change to limit: 2 then it returns a proper result.
    If you change the block height range to something that hasn't been mined yet, then you get a proper empty array as result, with both limit: 1 and limit: 2.

  3. A60AB5450353F40E commented on Mar 1, 2023

    @A60AB5450353F40E
    Author

    Also, this one which selects only 1 block trips with the same error. Change _gte and _lt heights +1 and it returns empty array proper. Commenting out the redeem_bytecode_pattern makes it return empty array, so I suspect some bug there.

    # Matches all spends from AnyHedge v0.11 contract template
    # https://gitlab.com/GeneralProtocols/anyhedge/contracts/-/blob/development/contracts/v0.11/bytecode.asm
    query {
      input(
        #limit: 10
        #offset: 0
        where: {
          transaction: {
            block_inclusions: {
              block: {
                height: { _gte: 781888, _lt: 781889 }
                accepted_by: { node: { name: { _eq: "bchn-mainnet" } } }
              }
            }
          }
          _or: [
            { unlocking_bytecode_pattern: { _eq: "40104010514d" } }
            { unlocking_bytecode_pattern: { _eq: "4141004d" } }
          ]
          redeem_bytecode_pattern: {
            _regex: "04040[2-4]0[2-4]0[2-8]0[2-8]21(17|19|23)(17|19|23)(00|51)21215c79009c637b695c7a7cad5b7a7cad6d6d6d6d6d51675c7a519dc3519d5f7a5f795779bb5d7a5d79577abb5c79587f77547f75817600a0695c79587f77547f75818c9d5c7a547f75815b799f695b795c7f77817600a0695979a35879a45c7a547f7581765c7aa2695b7aa2785a7a8b5b7aa5919b690276587a537a96a47c577a527994a4c4529d00cc7b9d00cd557a8851cc9d51cd547a8777777768"
          }
        }
      ) {
        transaction {
          block_inclusions {
            block {
              height
              timestamp
            }
          }
          inputs {
            outpoint_transaction_hash
            outpoint_index
            outpoint {
              value_satoshis
              locking_bytecode
              locking_bytecode_pattern
              transaction {
                block_inclusions {
                  block {
                    height
                    timestamp
                  }
                }
              }
            }
            unlocking_bytecode
            unlocking_bytecode_pattern
            redeem_bytecode_pattern
          }
        }
      }
    }
    
  4. A60AB5450353F40E commented on Mar 27, 2023

    @A60AB5450353F40E
    Author

    Replacing regex with like fails on some blocks, too:

    Query

    # Matches all spends from AnyHedge v0.11 contract template
    # https://gitlab.com/GeneralProtocols/anyhedge/contracts/-/blob/development/contracts/v0.11/bytecode.asm
    query {
      input(
        #limit: 0
        #offset: 0
        where: {
          transaction: {
            block_inclusions: {
              block: {
                height: { _gte: 785576, _lt: 785577 }
                accepted_by: { node: { name: { _like: "%mainnet" } } }
              }
            }
          }
          _or: [
            { unlocking_bytecode_pattern: { _eq: "40104010514d" } }
            { unlocking_bytecode_pattern: { _eq: "4141004d" } }
          ]
          redeem_bytecode_pattern: {
            #_regex: "04040[2-4]0[2-4]0[2-8]0[2-8]21(17|19|23)(17|19|23)(00|51)21215c79009c637b695c7a7cad5b7a7cad6d6d6d6d6d51675c7a519dc3519d5f7a5f795779bb5d7a5d79577abb5c79587f77547f75817600a0695c79587f77547f75818c9d5c7a547f75815b799f695b795c7f77817600a0695979a35879a45c7a547f7581765c7aa2695b7aa2785a7a8b5b7aa5919b690276587a537a96a47c577a527994a4c4529d00cc7b9d00cd557a8851cc9d51cd547a8777777768"
            _like: "%21215c79009c637b695c7a7cad5b7a7cad6d6d6d6d6d51675c7a519dc3519d5f7a5f795779bb5d7a5d79577abb5c79587f77547f75817600a0695c79587f77547f75818c9d5c7a547f75815b799f695b795c7f77817600a0695979a35879a45c7a547f7581765c7aa2695b7aa2785a7a8b5b7aa5919b690276587a537a96a47c577a527994a4c4529d00cc7b9d00cd557a8851cc9d51cd547a8777777768"
          }
        }
      ) {
        transaction {
          block_inclusions {
            block {
              height
              timestamp
            }
          }
          inputs {
            outpoint_transaction_hash
            outpoint_index
            outpoint {
              value_satoshis
              locking_bytecode
              locking_bytecode_pattern
              transaction {
                block_inclusions {
                  block {
                    height
                    timestamp
                  }
                }
              }
            }
            unlocking_bytecode
            unlocking_bytecode_pattern
            redeem_bytecode_pattern
          }
        }
      }
    }
    

    Result

    {
      "errors": [
        {
          "extensions": {
            "code": "data-exception",
            "path": "$"
          },
          "message": "negative substring length not allowed"
        }
      ]
    }
    
  5. mainnet-pat commented on Apr 6, 2025

    @mainnet-pat

    #70 Fixes this issue.

    However, the queries searching by unlocking_bytecode_pattern are still unusable as they scan the entire input dataset and fail to complete in statement_timeout timespan. I am not sure if it is possible to add an index for a computed field. But it could be meaningful to materialize this field as a column.

  6. added a commit that references this issue on May 10, 2026
    cf64c67
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions