Skip to content

encode_args encodes multiple arguments as single record instead of separate arguments #52

Description

@dicolasi

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,
phone_number: Option,
) -> 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(),
"test@example.com".to_string(),
"John".to_string(),
"Doe".to_string(),
None::,
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", "test@example.com", "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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions