pocketic icon indicating copy to clipboard operation
pocketic copied to clipboard

encode_args encodes multiple arguments as single record instead of separate arguments

Open dicolasi opened this issue 2 months ago • 0 comments

When using encode_args((arg1, arg2, arg3, ...)) in PocketIC tests to call canister methods with multiple arguments, the macro encodes the tuple as a single Candid record (table0) instead of encoding each argument separately. This causes deserialization failures in the receiving canister.

Environment PocketIC version: 10.0.0 Candid version: 0.10.20 ic-cdk version: 0.18 Expected Behavior Multiple arguments should be encoded as separate Candid arguments, matching the behavior of the real IC replica and dfx canister call.

Actual Behavior encode_args((arg1, arg2, arg3, ...)) encodes the tuple as a single record argument, causing:

Fail to decode argument 0 from table0 to <expected_type> Caused by: Subtyping error: Type mismatch Reproduction Canister method:

rust #[update] fn create_user( user_type_str: String, currency_str: String, email: String, first_name: String, last_name: String, principal_id: Option<String>, phone_number: Option<String>, ) -> Result<User, String> { ... } PocketIC test:

rust use candid::encode_args;

let result = pic.update_call( canister_id, Principal::anonymous(), "create_user", encode_args(( "User".to_string(), "UGX".to_string(), "[email protected]".to_string(), "John".to_string(), "Doe".to_string(), None::<String>, Some("+256700123456".to_string()), )).unwrap(), ); Error:

Panicked at 'called Result::unwrap() on an Err value: Custom(Fail to decode argument 0 from table0 to text Caused by: Subtyping error: text)' Verification The SAME code works perfectly on local IC replica:

bash dfx canister call data_canister create_user
'("User", "UGX", "[email protected]", "John", "Doe", null, opt "+256700123456")'

✅ Returns: Ok(User { ... })

Workarounds Attempted ❌ Using Encode! macro: Encode!(&arg1, &arg2, ...).unwrap() - still encodes as record ❌ Using ic_cdk::call - deprecated and has same issue ❌ Passing struct instead - causes enum serialization issues Impact This makes it impossible to write PocketIC integration tests for canisters with multi-argument methods, forcing developers to:

Use local IC replica for all testing (much slower) Artificially limit APIs to single-argument methods Skip integration tests Expected Fix encode_args should encode tuples as separate Candid arguments (not a single record), matching real IC behavior.

dicolasi avatar Nov 10 '25 10:11 dicolasi