NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #4772 most downloaded on crates.io
Candid is an interface description language (IDL) for interacting with canisters running on the Internet Computer.
Last release 12 days ago
25 Sep 2026
Release timing varies
gaps range from 2 weeks to 4 months
Some releases are documented
notes for 32 of the last 60 stable releases
4 versions withdrawn
withdrawn after publishing
6 years old
121 releases · first in 2020
One column per quarter.
Patch release of candid / candid_derive, 0.10.36 → 0.10.37. No source changes — it dates the two decoder fixes already on master.
chore: Release candid 0.10.37 (#772)
Patch release of `candid` / `candid_derive`, 0.10.36 → 0.10.37. No
source changes — it dates the two decoder fixes already on `master`.
## Summary
- Bump `candid` and `candid_derive` 0.10.36 → 0.10.37, and the `=` pin
between them
- Date the `Unreleased` changelog entries as `2026-09-25` / `Candid
0.10.37`, covering:
+ Bounding the byte length of the type-table header, 64 KiB by default
and configurable with `set_max_header_len` (#770)
+ Bounding the size of a type named in a decoder diagnostic, so its
rendering no longer follows the type's own width and depth (#771)
- Refresh `Cargo.lock`, `rust/bench/Cargo.lock`, `tools/ui/Cargo.lock`
and `rust/candid/fuzz/Cargo.lock`
`candid_parser` is unchanged at 0.4.1; its dependency on `candid` is a
`0.10.16` floor, so it needs no bump.
The lockfile diffs are version bumps only — no dependency churn.
## All four lockfiles this time
The 0.10.36 release noted that `rust/candid/fuzz/Cargo.lock` was stale
at 0.10.34 and that all four lockfiles should move together as a
release-checklist step. This one does that, so `fuzz` goes 0.10.34 →
0.10.37.
`tools/ui` patches `candid` to the workspace path, so its lockfile pins
the path crate's version and has to move with the bump.
`candid-ui-release.yml` builds `didjs` there with `--locked` and
triggers on the date tag, so a stale lock would only fail at tag time,
after merge.
## Test plan
- [x] `cargo check -p candid -p candid_derive -p candid_parser`
- [x] `cargo test -p candid --features all` — all suites pass
- [x] `cd tools/ui && cargo build --target wasm32-unknown-unknown
--profile canister --package didjs --locked` — the release workflow's
exact command, succeeds
- [x] `cd rust/candid/fuzz && cargo check`
- [ ] Reviewer to confirm release scope and changelog date
## After merge
1. Tag `2026-09-25` on `master` — this is what `candid-ui-release.yml`
triggers on to publish the `candid_ui` canister wasm
2. Run the **Crates Publish** workflow (`workflow_dispatch`) with the
`candid` input checked, which publishes `candid_derive` then `candid`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
DecoderConfig::set_max_header_len. Headers over the bound, far above any realistic interface, are now rejected; the value section is unaffected, and set_max_type_len still separately bounds the number of type-table entries.set_full_error_message(true) selects; ordinary mismatches are unchanged and still name both types.2026-09-25: chore: Release candid 0.10.37 (#772) Latest
Latest
Compare
Scope the decode fast paths of a map to their own half of an entry, so a map entry's key and value each decode under their own declared type. deserial
deserialize_map derives a big-integer fast path from the map's value type and a text fast path from its key type; each previously stayed active for the whole entry. The big-integer path is now cleared for the duration of the key and restored for the value, the text path is cleared for the duration of the value, and the value's expected and wire types are re-established on every entry. Each half of an entry therefore goes through its own type's entry point, keeping its own encoding (SLEB128 for int, LEB128 for nat) and its own subtype check, for every combination of key and value type — including a value whose type shares an encoding with the key's, such as blob against text. The wire format is unchanged, and entries whose key and value types agree decode identically.opt. The queue is only mutated at the top level, so it is now shared rather than copied and the snapshot is a refcount bump. Skipping many present optional arguments is no longer superlinear in the argument count; the decode result is unchanged.Bound the allocation when reading a length-prefixed byte field in the type-table header. A byte vector (a future type's payload, or a service method's
Fix decoding a vec of fixed-width primitives into newtype elements (e.g. struct EventIndex(u32)), which failed with a spurious subtyping error since 0
vec of fixed-width primitives into newtype elements (e.g. struct EventIndex(u32)), which failed with a spurious subtyping error since 0.10.27. The bulk decode fast path fed each element through serde's value deserializers, which do not implement deserialize_newtype_struct; they now go through a wrapper that forwards it, as the main deserializer does. Nested newtypes are unwrapped recursively.is_human_readable() reporting true for elements of a vec of fixed-width primitives, also since 0.10.27. The bulk decode fast path inherited serde's default from the same value deserializers, so a Deserialize impl that branches on it took its human-readable path inside a vec while taking the binary path everywhere else, silently decoding to a different value with no error. It now reports false for the whole decoder, as candid is a binary format.Migrated from the deprecated `binread` crate to its successor binrw. The types in the candid::binary_parser module (Header, PrincipalBytes, Len, BoolV…
Breaking changes:
Migrated from the deprecated binread crate to its successor binrw. The types in the candid::binary_parser module (Header, PrincipalBytes, Len, BoolValue) now implement binrw::BinRead instead of binread::BinRead, and From<binread::Error> for candid::Error is replaced by From<binrw::Error>.
Released as a patch rather than a minor bump because the affected surface is limited to those trait impls. binary_parser is an internal wire-format parsing module that is pub only incidentally — it is used nowhere outside candid's own deserializer, and it is now #[doc(hidden)] to say so. Code is affected only if it depends on binread directly and names these impls; the wire format, decoder error messages, byte offsets, type layouts, and all function signatures are unchanged, so the worst case is a compile error rather than a behaviour change.
Non-breaking changes:
binrw migration, which drops binread's debug_template codegen: up to 37% fewer instructions on variant-heavy payloads (multi_arg −36.6%, result_variant −10.3%, large_variant −9.5%, subtype_decode −8.0%, double_option −7.0%), with no regressions.syn 1.x dependency tree that binread_derive pinned (along with rustversion).binrw::Error variant now degrades to a label-less error instead of panicking, since binrw::Error is #[non_exhaustive] and decoding runs on untrusted input.A service reference now decodes where a principal is expected: service is a subtype of principal (spec addition: service <: principal, modelled analog
principal is expected: service <actortype> is a subtype of principal (spec addition: service <: principal, modelled analogously to nat <: int). The subtype checker and the deserializer accept a service reference at type principal; the two share an identical wire encoding, so the coercion is the identity on the reference. The reverse (a principal at a service type) remains rejected.Encode and decode large Nat/Int values in linear time. Values beyond the u64/i64 fast path were previously processed one LEB128/SLEB128 group at a tim
Nat/Int values in linear time. Values beyond the u64/i64 fast path were previously processed one LEB128/SLEB128 group at a time, shifting the whole bignum on every byte (O(n²) in the encoded length); they now build the value in a single O(n) pass.Add pretty::sep_enclose and sep_enclose_space: list/tuple pretty-printing combinators that separate items and enclose them in delimiters, emitting a t
pretty::utils::sep_enclose and sep_enclose_space: list/tuple pretty-printing combinators that separate items and enclose them in delimiters, emitting a trailing separator on multi-line layouts.TypeEnv::to_sorted_iter() to iterate bindings in a deterministic, key-sorted order.Fix text_fast_path leakage between nested maps: an inner map with non-text keys would fail with a "Type mismatch" error when enclosed in an outer map
text_fast_path leakage between nested maps: an inner map with non-text keys would fail with a "Type mismatch" error when enclosed in an outer map with text keysFix LEB128/SLEB128 fast path silently truncating Nat/Int values near the u64/i64 boundary during decoding
Nat/Int values near the u64/i64 boundary during decodingInt::decode truncating large magnitudes due to fast-path leakageAdd subtype_check_all() to collect all subtype errors in one pass (previously stopped at the first)
subtype_check_all() to collect all subtype errors in one pass (previously stopped at the first)Incompatibility type and format_report() for structured, hierarchical error reportingFix decoding failure when a trailing argument is a primitive vector
Preserve Rust doc comments on exported Candid types, record fields, and variant members when generating .did files via #[derive(CandidType)]
.did files via #[derive(CandidType)]Implement DataSize for Principal, enabling Principal as an element type in BoundedVec
DataSize for Principal, enabling Principal as an element type in BoundedVecAdd BoundedVec type to candid::bounded_vec for bounding a vector by number of elements, total data size, and per-element data size during deserializat
BoundedVec type to candid::types::bounded_vec for bounding a vector by number of elements, total data size, and per-element data size during deserializationUse target_family = "wasm" for platform detection to cover both wasm32 and wasm64; skip recursion check on wasm (sandboxed), use stack-based check on
target_family = "wasm" for platform detection to cover both wasm32 and wasm64; skip recursion check on wasm (sandboxed), use stack-based check on native platforms and a conservative depth limit on other niche platformsTypeEnv::is_empty, trace_type, rec_find_type, as_func, as_service), value type annotation (IDLValue::annotate_type), subtype checking (subtype_(), equal()), and all deserializer methods (deserialize_option, deserialize_seq, deserialize_map, deserialize_tuple, deserialize_tuple_struct, deserialize_struct, deserialize_enum)RecursionDepth with DepthGuard) for automatic depth management, eliminating manual increment/decrement operationsAdd max_type_len to DecoderConfig to configure the type table size limit (default: 10,000) during binary parsing.
max_type_len to DecoderConfig to configure the type table size limit (default: 10,000) during binary parsing.fix: subtyping and coercion rules for optional types
reserved at any context do not coerce into values of type nullnull in the textual format are decoded into a default valueFixes a compatibility issue with serde v1.0.220 and later.
serde v1.0.220 and later.Implement serde::Serialize and PartialOrd, Ord, Hash for the Reserved type.
serde::Serialize and PartialOrd, Ord, Hash for the Reserved type.Fixes a regression in pretty printing when concatenating an empty list of documents
Makes the warning message for the special opt subtyping rule more explicit in the candid::subtype::subtype and candid::subtype::subtype_with_config fu
candid::types::subtype::subtype and candid::types::subtype::subtype_with_config functions.pp_label_raw in pretty::candid module.Nothing published for this version
Add a series of decoder functions which provide convenience for ic-cdk macros usage.
Add ArgumentEncoder::encode_ref, utils::{write_args, encode_args} that don't consume the value when encoding.
ArgumentEncoder::encode_ref, utils::{write_args, encode_args} that don't consume the value when encoding.Implement CandidType for std::PhantomData.
CandidType for std::marker::PhantomData.Add IDLBuilder.try_reserve_value_serializer_capacity() to reserve capacity before serializing a large amount of data.
IDLBuilder.try_reserve_value_serializer_capacity() to reserve capacity before serializing a large amount of data.Add candid::MotokoResult type. Use motoko_result.into_result() to convert the value into Rust result, and rust_result.into() to get Motoko result.
candid::MotokoResult type. Use motoko_result.into_result() to convert the value into Rust result, and rust_result.into() to get Motoko result.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Switch HashMap to BTreeMap in serialization and T::ty(). This leads to around 20% perf improvement for serializing complicated types.
HashMap to BTreeMap in serialization and T::ty(). This leads to around 20% perf improvement for serializing complicated types.text_sizeCandidType for serde_bytes::ByteArraypretty::candid::pp_init_args function to pretty print init argsSupport #[serde(rename = "")] with arbitrary string.
#[serde(rename = "")] with arbitrary string.candid::decode_args_with_config, candid::utils::decode_args_with_config_debug, candid::decode_one_with_config, candid::Decode!([config]; &bytes, T), candid::Decode!(@Debug [config]; &bytes, T), IDLArgs::from_bytes_with_types_with_config and IDLArgs::from_bytes_with_config. The original decoding method remains to be non-metered.Fix parser when converting vec { number } into blob type.
vec { number } into blob type.Fix display IDLValue::Blob to allow "\n\t" in ascii characters.
IDLValue::Blob to allow "\n\t" in ascii characters.Add candid::value::try_from_candid_type to convert Rust type to IDLValue.
candid::types::value::try_from_candid_type to convert Rust type to IDLValue.IDLValue::Blob in ascii character only when the whole blob are ascii characters.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Implement CandidType for std::Reverse.
CandidType for std::cmp::Reverse.pub for struct fields.merge_init_types and instantiate_candid when the main actor refers to a variable.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →