denoland/deno · error · syn::Error

invalid attribute for `{buf}` modifier

Error message

invalid attribute for `{buf}` modifier

What it means

For the `buffer`, `anybuffer`, and `arraybuffer` modifiers, op2 accepts a bare form (BufferMode::Default) or exactly one of the identifiers `unsafe`, `copy`, or `detach` in parentheses. The parser at libs/ops/op2/signature.rs raises this formatted error (naming the concrete modifier, e.g. `buffer`) for any other argument.

Source

Thrown at libs/ops/op2/signature.rs:1412

        )));
      }
    }

    buf @ "buffer" | buf @ "anybuffer" | buf @ "arraybuffer" => {
      let mode = if matches!(attr.meta, Meta::Path(_)) {
        BufferMode::Default
      } else {
        let ident: Ident = attr
          .parse_args()
          .map_err(AttributeError::InvalidAttribute)?;
        if ident == "unsafe" {
          BufferMode::Unsafe
        } else if ident == "copy" {
          BufferMode::Copy
        } else if ident == "detach" {
          BufferMode::Detach
        } else {
          return Err(AttributeError::InvalidAttribute(syn::Error::new(
            attr.span(),
            format!("invalid attribute for `{buf}` modifier"),
          )));
        }
      };

      let source = match buf {
        "buffer" => BufferSource::TypedArray,
        "anybuffer" => BufferSource::Any,
        "arraybuffer" => BufferSource::ArrayBuffer,
        _ => unreachable!(),
      };

      Some(AttributeModifier::Buffer(mode, source))
    }

    // async is a keyword and does not work as #[async] so we use #[async_method] instead
    "required" | "rename" | "method" | "getter" | "setter" | "fast"

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pick one of the three supported modes: `#[buffer(unsafe)]` (borrow without copy), `#[buffer(copy)]` (copy into Rust-owned memory), `#[buffer(detach)]` (take ownership by detaching the ArrayBuffer), or drop the parentheses for the default.
  2. Check spelling — the argument is a bare identifier matched by string equality (`unsafe`, `copy`, `detach`).
  3. Remember the modifier name in the message tells you which attribute (`buffer`, `anybuffer`, or `arraybuffer`) got the bad argument.

Example fix

// before
#[op2]
fn op_write(#[buffer(zero_copy)] buf: &[u8]) { /* ... */ }

// after
#[op2]
fn op_write(#[buffer(unsafe)] buf: &[u8]) { /* ... */ }
Defensive patterns

Strategy: validation

Validate before calling

// Compile-time: `cargo check`. Closed set per buffer modifier:
//   #[buffer] | #[buffer(unsafe)] | #[buffer(copy)] | #[buffer(detach)]
//   (same for anybuffer / arraybuffer)

Prevention

When it happens

Trigger: `#[buffer(shared)]`, `#[buffer(zero_copy)]`, `#[arraybuffer(resizable)]`, or a misspelling like `#[buffer(coppy)]`; also multiple arguments where one identifier is expected.

Common situations: Coming from other binding frameworks that have `shared`/`zero_copy` buffer modes and guessing those names; typos.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/dfd3c05eb0ae786e. Report an issue: GitHub.