rocklabs-io / ic-py

Python Agent Library for the DFINITY Internet Computer
MIT License
127 stars 26 forks source link

TypeError: object of type 'NoneType' has no len() #42

Closed letmejustputthishere closed 2 years ago

letmejustputthishere commented 2 years ago

When I run this code

from ic.client import Client
from ic.identity import Identity
from ic.agent import Agent
from ic.candid import encode, Types
import time
import schedule
import sys

# params is an array, return value is encoded bytes
# params = [{'type': Types.Nat, 'value': 10}]
# data = encode(params)

# Identity and Client are dependencies of Agent
iden = Identity()  # creates a random keypair
client = Client()  # creates a client to talk to the IC
# creates an agent, combination of client and identity
agent = Agent(iden, client)

def main():
    backup(canister_id=sys.argv[1])
    schedule.every(5).seconds.do(backup, canister_id=sys.argv[1])

    while True:
        schedule.run_pending()
        time.sleep(1)

def backup(canister_id):
    print(f"disburse completed at {time.ctime()}")
    # query the NFT canister
    # doesnt change after calling `shuffleAssets`
    result = agent.update_raw(
        canister_id, "disburse", encode([]))

    print(result) 

get the following error after a couple of iterations:

Traceback (most recent call last):
  File "/home/moritz/.venv/bin/backup", line 8, in <module>
    sys.exit(main())
  File "/home/moritz/.venv/lib/python3.8/site-packages/state_backup/backup.py", line 25, in main
    schedule.run_pending()
  File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 780, in run_pending
    default_scheduler.run_pending()
  File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 100, in run_pending
    self._run_job(job)
  File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 172, in _run_job
    ret = job.run()
  File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 661, in run
    ret = self.job_func()
  File "/home/moritz/.venv/lib/python3.8/site-packages/state_backup/backup.py", line 33, in backup
    result = agent.update_raw(
  File "/home/moritz/.venv/lib/python3.8/site-packages/ic/agent.py", line 92, in update_raw
    return decode(result)
  File "/home/moritz/.venv/lib/python3.8/site-packages/ic/candid.py", line 1123, in decode
    b = Pipe(data)
  File "/home/moritz/.venv/lib/python3.8/site-packages/ic/candid.py", line 45, in __init__
    self._view = buffer[0:len(buffer)]
TypeError: object of type 'NoneType' has no len()
letmejustputthishere commented 2 years ago

Maybe this is related to this? https://forum.dfinity.org/t/calling-a-counter-multiple-times-asynchronously-with-promise-all-gives-the-same-value-each-time/11618/

Myse1f commented 2 years ago

What's ur canister id? Then I could have a try,

letmejustputthishere commented 2 years ago

djkni-kiaaa-aaaae-qabua-cai

I tried to use different cron mechanisms, but all of them lead to the same error. Seems like calling the same update_raw in a small timeframe leads to this error.

letmejustputthishere commented 2 years ago

this also appears:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/moritz/ethflower-disburse/off-chain-backup/state_backup/backup.py", line 38, in main
    s.run()
  File "/home/moritz/.pyenv/versions/3.8.6/lib/python3.8/sched.py", line 151, in run
    action(*argument, **kwargs)
  File "/home/moritz/ethflower-disburse/off-chain-backup/state_backup/backup.py", line 27, in backup
    result = agent.update_raw(
  File "/home/moritz/ethflower-disburse/.venv/lib/python3.8/site-packages/ic/agent.py", line 91, in update_raw
    result = self.poll(canister_id, req_id)
  File "/home/moritz/ethflower-disburse/.venv/lib/python3.8/site-packages/ic/agent.py", line 121, in poll
    status, cert = self.request_status_raw(canister_id, req_id)
  File "/home/moritz/ethflower-disburse/.venv/lib/python3.8/site-packages/ic/agent.py", line 111, in request_status_raw
    cert = self.read_state_raw(canister_id, paths)
  File "/home/moritz/ethflower-disburse/.venv/lib/python3.8/site-packages/ic/agent.py", line 103, in read_state_raw
    d = cbor2.loads(ret)
_cbor2.CBORDecodeValueError: unknown unsigned integer subtype 0x1c
Myse1f commented 2 years ago

I ran ur code about serveral minutes, but no error occured. Can you find a specific method to reproduce the issue?

Besides, what's ur current version of ic-py.

letmejustputthishere commented 2 years ago

i updated to 1.0.0, thanks for the hint! i will keep an eye on it and see whether the error pops up again

letmejustputthishere commented 2 years ago

still happens :/

did you make sure you ran the code in the loop? i think repeatedly calling update_raw within a couple of seconds causes the issue

Myse1f commented 2 years ago

yes, I ran the code you provide.

letmejustputthishere commented 2 years ago

i'm running the code in this branch using python 3.8.6 on ubuntu 20.04 https://github.com/flowerpowerdao/off-chain-backup/tree/disburse

letmejustputthishere commented 2 years ago

you need to remove the except: pass to see the errors

Myse1f commented 2 years ago

Can you paste your error message here with new version?

letmejustputthishere commented 2 years ago

my bad, i didnt update the dependencies on my server! it works now and yields None instead of the errors from before. Why does that happen? Is the call failing or the IC not answering?

Myse1f commented 2 years ago

I think it’s timeout for waiting the result. Update call is asynchronous and we keep querying the result for 10s. If timeout, it returns None.

Maybe we can expose the argument for setting the timeout.

letmejustputthishere commented 2 years ago

With dfx I think i never had a timeout, why does it happen so frequently with ic-py?

letmejustputthishere commented 2 years ago

Maybe we can expose the argument for setting the timeout.

That would be cool

Myse1f commented 2 years ago

43

  1. update_raw timeout default to infinite
  2. update_raw(..., timeout=) to set the polling timeout