Different dfx versions produce different query results

When I was checking the operation of my deployed canisters, I was troubled by the fact that the dashboard returned normal values, but when I used local dfx, for some reason, no values were returned.
Finally, after updating the dfx version, the values were returned without any problems.
I have been using dfx since dfx 0.12.0, but this was the first time this happened.
I would like to know what kind of case or background this could happen.

As you can see from the command, I am running in an environment with network=ic, but if you deploy locally, it does not matter if your dfx is old (although in that case, the local node you are running on is also from the old dfx).

% dfxvm default 0.15.1
info: using existing install for dfx 0.15.1
info: set default version to dfx 0.15.1
% dfx --version
dfx 0.15.1
% dfx canister --ic call 6egpc-3yaaa-aaaal-qi5qa-cai query_between "(\
  \"stablecoin-rating:active-address:1:usdc:86400\", \
  record { \
    from_timestamp = opt 0;\
    to_timestamp = opt 9223372036854775807; \
  } \
)"
(vec {})

% dfxvm default 0.19.0                                                
info: using existing install for dfx 0.19.0
info: set default version to dfx 0.19.0
% dfx --version                                                       
dfx 0.19.0
% dfx canister --ic call 6egpc-3yaaa-aaaal-qi5qa-cai query_between "(\
  \"stablecoin-rating:active-address:1:usdc:86400\", \
  record { \
    from_timestamp = opt 0;\
    to_timestamp = opt 9223372036854775807; \
  } \
)"
(vec {})

Do you still have the problem even after updating the version?
If yes is it only for local or --network ic as well.
can you provide more data on that

Thanks for confirming.
I updated the version and now I can get the values. The background is that I would like to know why I can’t get the values if I don’t update the version. If dfx were to return an out of version error, that would still be fine, but the fact that the query is terminating successfully with the old version is troubling.

Without more details it’s hard to say, but my first guess would be Candid. The old dfx version does not read the on-chain candid file so it may make incorrect assumptions on how to decode certain values

Thanks for the support.

Without more details it’s hard to say

What information do you need to determine the cause?

The old dfx version does not read the on-chain candid file so it may make incorrect assumptions on how to decode certain values

In the old dfx, if you did not specify a did file as an argument, it would not be able to interpret strings such as key, but it could return some value as a structure.

Since this kind of event occurred while using 0.15.1, we can try to avoid using older versions as much as possible. However, it is difficult to follow up immediately when a new dfx is released, and I suspect a bug in canister when I cannot get a response using an old dfx that was responding yesterday.
So I would like to understand the behavior in the background.

NVM, you have the canister id in OP, no need for extra info. I would bet record {from_timestamp:opt int64; to_timestamp:opt int64} is the ‘problem’:

  • Candid (and therefore dfx) by default encodes numbers to int
  • An opt int that you try to decode to opt int64 doesn’t produce a type error but instead null. You can try it like this:
❯ didc encode '(opt 5)' | didc decode -t '(opt int64)'
(null)

❯ didc encode '(opt 5 : opt int64)' | didc decode -t '(opt int64)'
(opt (5 : int64))
  • Since you don’t explicitly specify a candid file and don’t use a canister name (so dfx doesn’t know about the candid file via dfx.json either), the old dfx defaults to opt int. The newer dfx version is able to download the candid file from chain (it basically does dfx canister metadata 6egpc-3yaaa-aaaal-qi5qa-cai candid:service --ic) and then encodes the timestamps as opt int64, which gets decoded correctly

If you want the correct results using an old dfx version, you can either add --candid path/to/can.did to the call or reference the canister with a name that you define in a dfx.json file that also points to the right candid file

Thanks for taking a deeper look.

I felt I understood it by doing it on my own.
This is not due to a wrong Query Response by the old dfx, but due to the parameters of the Query call not being what was intended, correct?
You are saying that because you did not explicitly specify opt int64 in the query parameter, it could not be interpreted when interpreting the parameter and was treated as null.
So I understood that when using the old dfx, I need to explicitly specify the argument type of the canister function I am calling and make the canister call (Or set .did file as an option). Am I correct?

Yes, that is correct. IIRC this is called ‘special opt rule’ in Candid but I can’t find docs to point to…

1 Like

Sorry for the late reply, thanks for all the support.
I have taken your answer as a solution.