PyO3/pyo3 · error · syn::Error
missing `message` in `warn` attribute
Error message
missing `message` in `warn` attribute
What it means
The #[pyo3(warn(...))] function attribute requires a `message` string. After parsing optional category and message key-value pairs, if no `message = "..."` was provided the parser fails with this syn::Error, since pyo3 always needs a warning message to emit.
Source
Thrown at pyo3-macros-backend/src/pyfunction.rs:215
if lookahead.peek(attributes::kw::message) {
message = content
.parse::<PyFunctionWarningMessageAttribute>()
.map(Some)?;
} else if lookahead.peek(attributes::kw::category) {
category = content
.parse::<PyFunctionWarningCategoryAttribute>()
.map(Some)?;
} else {
return Err(lookahead.error());
}
if content.peek(Token![,]) {
content.parse::<Token![,]>()?;
}
}
Ok(PyFunctionWarningAttribute {
message: message.ok_or(syn::Error::new(
content.span(),
"missing `message` in `warn` attribute",
))?,
category,
span,
})
}
}
impl ToTokens for PyFunctionWarningAttribute {
fn to_tokens(&self, tokens: &mut TokenStream) {
let message_tokens = self.message.to_token_stream();
let category_tokens = self
.category
.as_ref()
.map_or(quote! {}, |cat| cat.to_token_stream());
let token_stream = quote! {View on GitHub (pinned to ac9b6899d3)
Solutions
- Add `message = "..."` inside the warn attribute
- Keep the category if desired: warn(category, message = "...")
- Remove the warn attribute if no warning was intended
Example fix
// before
#[pyo3(warn(PendingDeprecationWarning))]
#[pyfunction]
fn old_api() {}
// after
#[pyo3(warn(PendingDeprecationWarning, message = "old_api is deprecated"))]
#[pyfunction]
fn old_api() {} Defensive patterns
Strategy: validation
Validate before calling
// before compiling, verify warn attributes carry a message
if let Some(i) = attr.find("warn(") {
assert!(attr[i..].contains("message"), "warn needs message = \"...\"");
} Prevention
- Always include message = "..." in #[pyo3(warn(...))]
- Copy complete examples from pyo3 docs
- cargo check after adding warn attributes
When it happens
Trigger: Writing `#[pyo3(warn(DeprecationWarning))]` or `#[pyo3(warn)]` without `message = "..."` on a #[pyfunction].
Common situations: Developers copying only the warning category from docs/examples that show a fuller form; assuming the category alone is sufficient as with Python's warnings.warn defaults.
Related errors
- `get` may only be specified once
- `set` may only be specified once
- `name` may only be specified once
- Python doc may not contain nul byte, found nul at position {
- Neither abi3 or abi3t features are enabled
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/ef1504b60b44a5fe.
Report an issue: GitHub.