rolldown/rolldown · error

ModuleType token should be followed by a string, but got

Error message

ModuleType token should be followed by a string, but got {other:?}

What it means

The `moduleType` operator in a filter expression must be followed immediately by a string literal naming the module type. The parser (`rec`, invoked from public `parse`) bails with this error when any other token follows the `moduleType` token, because `FilterExpr::ModuleType` only carries a string.

Solutions

  1. Quote the module type value, e.g. `moduleType('js')`.
  2. Verify the expression is complete and not truncated after the `moduleType` token.
  3. Use only string module type values matching known module types (js, jsx, ts, css, json, asset, ...).

Example fix

// before
parse("moduleType(/css/)")
// after
parse("moduleType('css')")
Defensive patterns

Strategy: validation

Validate before calling

// before serializing moduleType filter
function assertModuleType(v) {
  if (typeof v !== 'string') {
    throw new TypeError(`moduleType expects a string, got: ${typeof v}`);
  }
}

Type guard

function isStringModuleType(v) {
  return typeof v === 'string' && v.length > 0;
}

Try / catch

try {
  parse(expr);
} catch (e) {
  if (String(e).includes('ModuleType token should be followed by a string')) {
    // correct the expression: moduleType('...')
  }
  throw e;
}

Prevention

When it happens

Trigger: Parsing an expression like `moduleType(/regex/)` or `moduleType(true)`, or an expression that ends right after `moduleType` so a leftover/truncated token is popped instead of a string.

Common situations: Typos in hand-written serialized filter expressions used by builtin plugin filters; passing a regex instead of a string for the module type; string truncation when the expression is embedded in JSON config and quotes are mis-escaped.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of rolldown/rolldown@91b44b9d7b (2026-09-07). Data as JSON: /api/errors/47cfb95bd31fc5c4. Report an issue: GitHub.

Appendix: source

Thrown at crates/rolldown_utils/src/filter_expression.rs:301

        let key = match pop(tokens)? {
          Token::String(key) => key,
          other => anyhow::bail!("key of `Query` should be a string, but got {other:?}"),
        };
        let value = match pop(tokens)? {
          Token::String(v) => QueryValue::String(v),
          Token::Regex(v) => QueryValue::Regex(v),
          Token::Boolean(v) => QueryValue::Boolean(v),
          other => anyhow::bail!(
            "value of `Query` should be a string, regex, or boolean, but got {other:?}"
          ),
        };
        Ok(FilterExpr::Query(key, value))
      }
      Token::ModuleType => {
        let string = match pop(tokens)? {
          Token::String(s) => s,
          other => {
            anyhow::bail!("ModuleType token should be followed by a string, but got {other:?}")
          }
        };
        Ok(FilterExpr::ModuleType(string))
      }
      Token::And(arg_count) => {
        let mut args = Vec::with_capacity(arg_count as usize);
        for _ in 0..arg_count {
          args.push(rec(tokens)?);
        }
        Ok(FilterExpr::And(args))
      }
      Token::Or(arg_count) => {
        let mut args = Vec::with_capacity(arg_count as usize);
        for _ in 0..arg_count {
          args.push(rec(tokens)?);
        }
        Ok(FilterExpr::Or(args))
      }

View on GitHub (pinned to 91b44b9d7b)