denoland/deno · error · AnyError
Invalid filter
Error message
Invalid filter "{input}" What it means
Thrown by `deno outdated` / `deno pm outdated` when a string passed via `--filters` cannot be parsed into a package pattern plus optional version requirement. The parser splits the filter on '@' (special-casing '@scope/name@version') and feeds the version part to `deno_semver`'s `VersionReq::parse_from_specifier`; anything that fails semver parsing, or a filter with an empty pattern, produces this error with the raw input echoed back.
Solutions
- Correct the separator: use `@` between name and version, e.g. `--filters "foo@^2.0.0"` instead of `"foo=^2.0.0"`.
- Remove or fix the version segment so it is a valid semver range accepted by Deno (`^1.2.3`, `~1.2`, `1.x`, `*`); bare `foo` with no version is also valid.
- For scoped packages keep the full form `@scope/pkg@^1.0.0`; a leading '!' negates (`!@scope/pkg`).
- Use '*' as a wildcard inside the pattern (`foo*`), never inside the version segment.
Example fix
# before deno outdated --filters "foo=^2.0.0" # after deno outdated --filters "foo@^2.0.0"
Defensive patterns
Strategy: validation
Validate before calling
const FILTER_RE = /^!?(@[\w.-]+\/)?[\w.*-]+(@[^@\s]+)?$/;
function assertValidFilter(filter: string): void {
if (!FILTER_RE.test(filter)) {
throw new Error(`Invalid filter "${filter}"`);
}
} Type guard
function isValidFilter(f: string): boolean {
return /^!?(@[\w.-]+\/)?[\w.*-]+(@[^@\s]+)?$/.test(f);
} Try / catch
try {
await runDeno(['outdated', `--filters=${filter}`]);
} catch (e) {
if (String(e.message).includes('Invalid filter')) {
// show the expected '<name>[@<semver-range>]' syntax to the user
}
} Prevention
- Use '@' (not '=' or ':') between package name and version range in --filters.
- Validate filter strings in tooling/scripts before shelling out to deno.
- Keep version segments to plain semver ranges (^1.2.3, ~1.2, 1.x, *).
When it happens
Trigger: Running `deno outdated --filters "foo=^2.0.0"` (using '=' instead of '@'); a version segment that is not a valid semver range such as `@2.` or `@latest`; a filter like `"@"` where split('@') yields no pattern; a scoped filter `"@scope/pkg@not-a-version"`. The same message is also attached as context when the pattern fails regex compilation.
Common situations: Muscle memory from npm/jest CLI syntax (`pkg=^2`), copying a filter from another tool that uses commas differently, or typos in the version range. Note that `--filters` takes the version after '@', not after '=' or ':'.
Understand the failure class
Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.
Related errors
- Invalid semver version
- An executable name was not provided. One could not be…
- app name resolves its to , which is already part of the…
- bundle identifier must be in reverse-DNS form (e.g…
- bundle identifier must match [A-Za-z0-9.-]+, but contains
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/b45bc1a61e4f0f52.
Report an issue: GitHub.
Appendix: source
Thrown at cli/tools/pm/outdated/mod.rs:753
if let Some(scope_name) = s.strip_prefix('@') {
if let Some(idx) = scope_name.find('@') {
let (pattern, version_spec) = s.split_at(idx + 1);
(
pattern,
Some(
VersionReq::parse_from_specifier(
version_spec.trim_start_matches('@'),
)
.with_context(|| format!("Invalid filter \"{input}\""))?,
),
)
} else {
(s, None)
}
} else {
let mut parts = s.split('@');
let Some(pattern) = parts.next() else {
return Err(anyhow!("Invalid filter \"{input}\""));
};
(
pattern,
parts
.next()
.map(VersionReq::parse_from_specifier)
.transpose()
.with_context(|| format!("Invalid filter \"{input}\""))?,
)
};
Ok(Filter {
kind,
regex: pattern_to_regex(pattern)
.with_context(|| format!("Invalid filter \"{input}\""))?,
version_spec,
})
}View on GitHub (pinned to 9ad36f7a2c)