denoland/deno · error · syn::Error

expected attribute arguments in parentheses: `{}(...)`

Error message

expected attribute arguments in parentheses: `{}(...)`

What it means

`CustomMeta::require_list` in libs/ops/op2/config.rs returns the attribute's parenthesized arguments as a `MetaList`. If the attribute was written as a bare path (or a name=value) with no `(...)` group, `as_meta_list()` yields `None` and this error is raised on the attribute identifier, asking for the `ident(...)` form.

Source

Thrown at libs/ops/op2/config.rs:384

      None
    };

    Ok(CustomMeta { ident, args })
  }
}

impl CustomMeta {
  pub fn as_meta_list(&self) -> Option<MetaList> {
    self.args.clone().map(|(delimiter, tokens)| MetaList {
      path: syn::Path::from(self.ident.clone()),
      delimiter,
      tokens,
    })
  }

  pub fn require_list(&self) -> Result<MetaList, syn::Error> {
    self.as_meta_list().ok_or_else(|| {
      syn::Error::new(
        self.ident.span(),
        format!(
          "expected attribute arguments in parentheses: `{}(...)`",
          self.ident
        ),
      )
    })
  }
}

impl ToTokens for CustomMeta {
  fn to_tokens(&self, tokens: &mut TokenStream) {
    match self.as_meta_list() {
      Some(list) => {
        list.to_tokens(tokens);
      }
      _ => {
        self.ident.to_tokens(tokens);

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Add parentheses with the required arguments: `#[op2(webidl(...))]`, `#[op2(validate(...))]` — the error message names the exact identifier it wants arguments for.
  2. If you intended a flag with no arguments, you are using the wrong flag name; check op2's flag list for the bare-path variant.
  3. Consult a nearby op in the same crate (ext/ is full of examples) for the argument shape this attribute expects.

Example fix

// before
#[op2(webidl)]
#[string] fn op_get_color(color: &str) -> String { /* ... */ }

// after
#[op2(webidl(default = Color::Red))]
#[string] fn op_get_color(color: &str) -> String { /* ... */ }
Defensive patterns

Strategy: validation

Validate before calling

// Compile-time only: keep `cargo check` in CI and read the combined parse errors.
// Habit: argument-taking op2 attributes are always written as `name(...)` — never a bare path.

Prevention

When it happens

Trigger: Writing an op2/webidl sub-attribute that requires arguments without the parentheses, e.g. `#[op2(webidl)]` where the parser needs `webidl(...)` (as consumed via `input.parse::<CustomMeta>()?.require_list()`), or `#[op2(validate)]` instead of `#[op2(validate(path = "..."))]`.

Common situations: Converting a boolean-style flag into an argument-taking one during upgrades; trimming 'unnecessary' parentheses from a copy-pasted attribute; IDE auto-completing the bare path form.

Related errors


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