rolldown/rolldown · error
`QueryKey` should be followed by `QueryValue`, but got
Error message
`QueryKey` should be followed by `QueryValue`, but got `{:?}` What it means
When normalizing filter-expression tokens, a `QueryKey` token must be immediately followed by a `QueryValue` token (e.g. `id` query key followed by its value). If the next token has a different kind, normalization fails with this error describing the actual next kind.
Solutions
- Ensure every `QueryKey` token is immediately followed by a `QueryValue` token
- Check the filter expression string for a query written as `?key` without `=value` and add the value
- Verify programmatic token arrays are not missing elements (shifted kinds)
- Inspect the reported `{:?}` kind in the message to see which wrong token followed
Example fix
// before
filters: [{ kind: 'importerId', query: { key: 'ext' } }] // missing value
// after
filters: [{ kind: 'importerId', query: { key: 'ext', value: 'js' } }] Defensive patterns
Strategy: validation
Validate before calling
function validateQueryPairs(tokens) {
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].kind === 'QueryKey' && tokens[i + 1]?.kind !== 'QueryValue') {
throw new Error(`QueryKey at ${i} not followed by QueryValue`);
}
}
} Try / catch
try {
const compiled = preCompileFilterExpr(tokens);
} catch (e) {
if (String(e).includes('QueryKey')) console.error('Malformed query pair in filter expression:', e.message);
throw e;
} Prevention
- Always write queries as key=value pairs, never bare keys
- Build query tokens with a helper that always emits key+value together
- Validate token arrays before calling the binding
When it happens
Trigger: Building a filter expression whose query part omits the value, e.g. an expression ending with a bare query key (`importerId?ext` without value), or a token array where the value token was dropped/mistyped so the next token is `QueryKey`, `String`, etc.
Common situations: Hand-writing query filters in `transformFilter`/hook filter expressions (`?` queries like `?query=value`) with a missing `=` value, or programmatic token arrays with dropped elements.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- `QueryValue` token should not appear without a preceding…
- key of `Query` should be a string, but got
- number values are not supported for query filter values
- token should be followed by a string or regex, but got
- expected a number payload, but got
AI-assisted analysis of rolldown/rolldown@91b44b9d7b (2026-09-07).
Data as JSON: /api/errors/8d6f56a03e0a85e4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rolldown_binding/src/options/plugin/types/binding_filter_expression.rs:152
ret.push(Token::And(take_payload(value)?.try_into_number()?));
}
FilterTokenKind::Or => {
ret.push(Token::Or(take_payload(value)?.try_into_number()?));
}
FilterTokenKind::Not => {
ret.push(Token::Not);
}
FilterTokenKind::Include => ret.push(Token::Include),
FilterTokenKind::Exclude => ret.push(Token::Exclude),
FilterTokenKind::CleanUrl => ret.push(Token::CleanUrl),
FilterTokenKind::QueryKey => {
let query_key = take_payload(value)?.try_into_string()?;
iter.next();
let next_token = iter.peek_mut().ok_or_else(|| {
anyhow::anyhow!("`QueryKey` should be followed by a `QueryValue` token")
})?;
if next_token.kind != FilterTokenKind::QueryValue {
anyhow::bail!(
"`QueryKey` should be followed by `QueryValue`, but got `{:?}`",
next_token.kind
);
}
let query_value = match take_payload(next_token)? {
BindingFilterTokenPayloadInner::StringOrRegex(string_or_regex) => match string_or_regex {
StringOrRegex::String(str) => Token::String(str),
StringOrRegex::Regex(regexp) => Token::Regex(regexp),
},
BindingFilterTokenPayloadInner::Boolean(v) => Token::Boolean(v),
BindingFilterTokenPayloadInner::Number(_) => {
anyhow::bail!("number values are not supported for query filter values");
}
};
ret.push(query_value);
ret.push(Token::String(query_key));
ret.push(Token::Query);
iter.next();View on GitHub (pinned to 91b44b9d7b)