Hello Serde Team,
I've encountered a compile-time panic when using #[derive(Deserialize)] in combination with #[serde(rename_all = "camelCase")] on a struct that has fields with non-ASCII identifiers (specifically, Chinese characters).
Summary
The serde_derive procedural macro appears to panic during compilation when it tries to apply the camelCase renaming rule to a field name containing multi-byte UTF-8 characters. The error message clearly indicates a byte-indexing issue on a non-char boundary, suggesting the renaming logic might be incorrectly assuming ASCII strings.
The issue does not occur if:
- The
#[serde(rename_all = "camelCase")] attribute is removed.
- The attribute is changed to
#[serde(rename_all = "PascalCase")].
This suggests the bug is specific to the implementation of the camelCase transformation logic.
Minimal Reproducible Example (MRE)
Here is the smallest possible Rust project that demonstrates the bug:
Cargo.toml:
[package]
name = "serde-cjk-bug-report"
version = "0.1.0"
edition = "2024"
[dependencies]
serde = { version = "1.0.219", features = ["derive"] }
src/main.rs:
use serde::Deserialize;
// This struct definition causes the compiler to panic.
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct TestPayload {
// Field name with Chinese characters
pub 项目名称: String,
pub 项目地址: String,
}
fn main() {
// The panic happens at compile time, so the main function's content
// doesn't matter, but it's here to make the example complete.
println!("This code will not compile.");
}
Compiler Panic Output
When trying to compile the MRE with cargo build, the compiler panics with the following output:
error: proc-macro derive panicked
--> src/main.rs:5:10
|
5 | #[derive(Deserialize, Debug, Clone)]
| ^^^^^^^^^^^
|
= help: message: byte index 1 is not a char boundary; it is inside '项' (bytes 0..3) of `项目名称`
Expected vs. Actual Behavior
- Expected Behavior: The code should compile successfully. The
camelCase rule, when applied to a field name like 项目名称 which has no case or separators to modify, should ideally result in no change to the name, or at least not cause a panic.
- Actual Behavior: The compiler panics with a fatal error related to string indexing.
Analysis
The panic message byte index 1 is not a char boundary strongly suggests that the string manipulation logic within the rename_all = "camelCase" implementation is incorrectly treating the UTF-8 field identifier as a sequence of bytes rather than characters. It attempts a byte-level index access, which is unsafe for multi-byte strings. A correct implementation should iterate over chars() rather than bytes().
Workarounds
For others encountering this issue, the current workarounds are:
- Avoid using non-ASCII field names if
rename_all is needed.
- Use ASCII field names and the
#[serde(rename = "项目名称")] attribute on each field individually.
- Remove the
rename_all attribute if the exact casing is not critical for your use case.
Environment
- Rust Version:
rustc 1.89.0 (29483883e 2025-08-04)
- Serde Version:
1.0.219
- OS: Windows 10
Thank you for maintaining this essential crate! I hope this report is helpful in resolving the issue.
Hello Serde Team,
I've encountered a compile-time panic when using
#[derive(Deserialize)]in combination with#[serde(rename_all = "camelCase")]on a struct that has fields with non-ASCII identifiers (specifically, Chinese characters).Summary
The
serde_deriveprocedural macro appears to panic during compilation when it tries to apply thecamelCaserenaming rule to a field name containing multi-byte UTF-8 characters. The error message clearly indicates a byte-indexing issue on a non-char boundary, suggesting the renaming logic might be incorrectly assuming ASCII strings.The issue does not occur if:
#[serde(rename_all = "camelCase")]attribute is removed.#[serde(rename_all = "PascalCase")].This suggests the bug is specific to the implementation of the
camelCasetransformation logic.Minimal Reproducible Example (MRE)
Here is the smallest possible Rust project that demonstrates the bug:
Cargo.toml:src/main.rs:Compiler Panic Output
When trying to compile the MRE with
cargo build, the compiler panics with the following output:Expected vs. Actual Behavior
camelCaserule, when applied to a field name like项目名称which has no case or separators to modify, should ideally result in no change to the name, or at least not cause a panic.Analysis
The panic message
byte index 1 is not a char boundarystrongly suggests that the string manipulation logic within therename_all = "camelCase"implementation is incorrectly treating the UTF-8 field identifier as a sequence of bytes rather than characters. It attempts a byte-level index access, which is unsafe for multi-byte strings. A correct implementation should iterate overchars()rather thanbytes().Workarounds
For others encountering this issue, the current workarounds are:
rename_allis needed.#[serde(rename = "项目名称")]attribute on each field individually.rename_allattribute if the exact casing is not critical for your use case.Environment
rustc 1.89.0 (29483883e 2025-08-04)1.0.219Thank you for maintaining this essential crate! I hope this report is helpful in resolving the issue.