How to migrate arg_data to ic_cdk v0.18

arg_data is deprecated in ic_cdk v0.18, and I’m not sure how to migrate my code. I couldn’t find anything about it in the migration guide.

Does anyone have an example?

Specifically, I need to update how I read arguments in my init functions. For example:

#[init]
fn init() {
    let call_arg = arg_data::<(Option<SegmentArgs>,)>(ArgDecoderConfig::default()).0;

The replacement function is listed in the deprecation notice. It’s just a renaming to msg_arg_data, matching the system interface’s name.

It isn’t just a renaming, msg_arg_data returns a Vec<u8> while arg_data provides the structured data.

pub fn arg_data<R: for<'a> ArgumentDecoder<'a>>(arg_config: ArgDecoderConfig) -> R {

// vs

pub fn msg_arg_data() -> Vec<u8> {

There is no exact equivalent of arg_data in ic-cdk v0.18.

In ic-cdk v0.18, you will need to use ic_cdk::api::msg_arg_data to get the argument bytes. Then use methods from candid crate to decode the bytes into the type you need. There are a few decode_* methods in candid::utils module. They are also re-exported in candid root module.

decode_args_with_config is the one with similar decoding experience.

Thanks. What’s the reasoning behind deprecating this function, if I may ask? Am I the only one using arg_data? Is it considered bad practice, and is there a more idiomatic way to read arguments in an init function? I’m just wondering why it vanished, whether I really need to create my own utility, or if there’s a recommended way to avoid that.

The original arg_data function has following signature:

pub fn arg_data<R: for<'a> ArgumentDecoder<'a>>(
    arg_config: ArgDecoderConfig,
) -> R

It takes a ArgDecoderConfig which is a wrapper of candid::DecoderConfig. It coupling too much with the candid decoding details. In ic-cdk v0.18, we removed this coupling. For replacement, we introduced the more versatile decode_with option in ic-cdk macros.

For example, you can use decide_with in #[init] as here. This is the PR introduced the macro option.

1 Like

Is there a reason you’re not using the function parameters?

#[init]
fn init(args: Option<SegmentArgs>) {
1 Like

Haha yeah, I also realized that after re-reading the doc following the last answer. I’m waiting for my CI to run on two PRs (and for dinner) before I comment and close the thread :wink:

Alright, CI is green. After reading @lwshang’s last answer, checking the documentation, and reviewing my code again, I realized there’s no good reason anymore to use arg_data. It was most likely just a legacy artifact rather than something that actually makes sense. So this turned out to be a good opportunity to migrate to using the function parameter directly, as shown above by @AdamS.

Thanks for your help!