{"record":{"id":"f3d1a1a400971067","repo":"denoland/deno","slug":"only-ascii-keys-are-supported","errorCode":null,"errorMessage":"Only ASCII keys are supported","messagePattern":"Only ASCII keys are supported","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"libs/ops/lib.rs","lineNumber":67,"sourceCode":"    Err(err) => err.into_compile_error().into(),\n  }\n}\n\n#[proc_macro_derive(ToV8, attributes(to_v8, v8))]\npub fn to_v8(item: TokenStream) -> TokenStream {\n  match conversion::to_v8::to_v8(item.into()) {\n    Ok(output) => output.into(),\n    Err(err) => err.into_compile_error().into(),\n  }\n}\n\nfn get_internalized_string(\n  name: syn::Ident,\n) -> Result<proc_macro2::TokenStream, syn::Error> {\n  let name_str = name.to_string();\n\n  if !name_str.is_ascii() {\n    return Err(syn::Error::new(\n      name.span(),\n      \"Only ASCII keys are supported\",\n    ));\n  }\n\n  Ok(quote::quote! {\n    ::deno_core::v8::String::new_from_one_byte(\n      __scope,\n      #name_str.as_bytes(),\n      ::deno_core::v8::NewStringType::Internalized,\n    )\n    .unwrap()\n    .into()\n  })\n}\n\n#[cfg(test)]\nmod infra {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/libs/ops/lib.rs#L49-L85","documentation":"deno_core's op/webidl macros build object keys with `v8::String::new_from_one_byte`, which only accepts one-byte (Latin-1) input. `get_internalized_string` in libs/ops/lib.rs therefore rejects any identifier used as a JS property key (op struct fields, webidl dictionary fields, enum tags, including camelCased js_names derived from field names) that contains non-ASCII characters.","triggerScenarios":"Naming a field of a struct used in `#[serde]`-style to_v8/from_v8 conversion, a webidl dictionary field, or an enum variant/tag with non-ASCII characters (accents, CJK, Cyrillic). Rust itself permits non-ASCII identifiers on nightly (`#![feature(non_ascii_idents)]`), but the macro rejects them because `#name_str.is_ascii()` fails.","commonSituations":"Writing bindings for an API whose domain model uses accented identifiers (e.g. `café`, `größe`) and mirroring those names into Rust structs passed to op2/webidl macros; enabling `non_ascii_idents` crate-wide and forgetting this macro restriction.","solutions":["Rename the Rust field/variant to an ASCII identifier; if the JS property name must stay non-ASCII, that is not supported by these macros at all.","Keep `non_ascii_idents` disabled in the crate so the compiler itself blocks such identifiers early.","If you only need a different ASCII JS name, use the rename mechanism (e.g. `#[webidl(rename = \"...\")]` with an ASCII value) instead of a non-ASCII Rust identifier."],"exampleFix":"// before (nightly non_ascii_idents)\n#[derive(WebIDL)]\n#[webidl(dictionary)]\nstruct FontOptions { pub fett: bool }\n// ...a field named `größe` fails: \"Only ASCII keys are supported\"\n\n// after\n#[derive(WebIDL)]\n#[webidl(dictionary)]\nstruct FontOptions { pub gross: bool }","handlingStrategy":"validation","validationCode":"// Keep the crate on stable Rust (no `non_ascii_idents` feature); stable rejects\n// non-ASCII identifiers before the macro ever runs:\n// [lib] ... (do NOT enable) #![feature(non_ascii_idents)]\n// Optional CI guard:\n// ! grep -rnP '[^\\x00-\\x7F]' --include='*.rs' src/ | grep -E 'fn |struct |enum ' && exit 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restrict all identifiers used in op/webidl types to ASCII — JS keys are built via one-byte v8 strings.","If the upstream API name is non-ASCII, transliterate the Rust field and accept the ASCII JS name it produces."],"tags":["proc-macro","identifier","non-ascii","v8","compile-time","op2","webidl"],"backgroundTag":"non-ascii-identifier","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}