A Karate runner calls `Runner.path("classpath:api").tags("~@ignore").parallel(4)`. Does the `~@ignore` do anything, and can any tag expression make an `@ignore`d Scenario run?
answer
- Some tags are decided before yours
- Redundant, not wrong
- You cannot ask for it back
- Line and name filters skip the layer
- A called feature ignores tags entirely
basics
~20 sKarate skips an @ignore scenario before the tag selector is evaluated, so ~@ignore is redundant, and no tag expression can select one back in. Only a line filter, a scenario-name filter or a call reaches it.
solid answer
~40 s`@ignore` is one of a handful of tags Karate handles itself, and the check runs **before** your selector. Scenario selection evaluates in a fixed order: `@ignore` present means skip; `@setup` present means skip; `@env=` must match the runner's `karateEnv(...)`; `@envnot=` must not match it; only then is your `tags(...)` expression evaluated. So `tags("~@ignore")` adds a condition that was already guaranteed, and `tags("@ignore")` still selects nothing. Karate's own documentation says as much — the tag is always skipped and you never need to write `~@ignore`. The ways an `@ignore`d scenario can still execute all bypass the tag layer entirely: a line filter such as `path("api.feature:31")`, a `scenarioName(...)` filter, or being reached by `call` from another feature.
code
gherkin · 19 linesFeature: order helpers
# never picked up by the runner - callable from other features
@ignore
Scenario: create a throwaway order
* def orderId = 'ord-' + java.util.UUID.randomUUID()
# never picked up by the runner - reachable via karate.setup()
@setup
Scenario: seed the catalogue
* def items = read('items.json')
# selection depends on the runner's karateEnv value
@envnot=prod
Scenario: reset the sandbox account
* url baseUrl
* path 'admin', 'reset'
* method post
* status 200go deeper
Recall that @ignore is built in and always skipped, so you never have to write ~@ignore, and asking for @ignore by tag will not bring those scenarios back.
Explain the ordering: line filter, name filter, called-feature bypass, then @ignore, @setup, @env and @envnot, and only then the tag expression you supplied.
Diagnose the environment asymmetry in a pipeline: @env=qa fails closed with no environment set while @envnot=prod fails open, which explains most suites that quietly shrink in CI.
Set the convention for what @ignore means in your codebase — permanently disabled, callable helper, or quarantined — because the runner cannot distinguish them and neither will anyone reading it later.
## The selection order Every top-level scenario passes through a fixed gauntlet before the runner decides to execute it. The order is what matters: 1. **Line filter** — if the path carried `file.feature:31`, only the scenario at that line runs, and it runs *regardless of tags*. 2. **`scenarioName(...)` filter** — same bypass semantics: an exact name match wins over the tag layer. 3. **Called, not top-level** — a feature reached by `call` from another feature ignores tag filtering altogether, so a helper feature does not need to be tagged into the run. 4. **`@ignore`** — present, so skip. No selector consulted. 5. **`@setup`** — present, so skip. No selector consulted. 6. **`@env=a,b`** — runs only when the runner's `karateEnv(...)` value is one of the listed values. 7. **`@envnot=a,b`** — skipped when the environment *is* one of them. 8. **Your `tags(...)` selector** — evaluated last, and only for scenarios that survived everything above. Steps 4 through 7 are the part candidates get wrong. They are not conditions layered onto your expression; they are decided first, and your expression never sees the scenario. ## Why `~@ignore` is dead weight Since step 4 already returns "skip", adding `not('@ignore')` to the selector changes nothing. Karate's own documentation states it plainly: the built-in `@ignore` tag is always skipped, and you do not need to specify `~@ignore` anywhere. It is harmless, but it is not free: - it teaches the next reader that `@ignore` is an ordinary tag, which it is not; - it hides the fact that the runner is unfiltered, so someone adding a real filter later must work out whether `~@ignore` was load-bearing; - and it invites the opposite mistake — believing that `tags("@ignore")` will run the ignored scenarios so you can check on them. It will not. The check is unconditional in both directions. ## The tags the runner decides for you | Tag | Effect at selection time | |---|---| | `@ignore` | never selected at top level | | `@setup` | never selected at top level; reachable only through the `karate.setup()` JavaScript API from inside the feature | | `@env=qa,dev` | runs only when the environment matches one of the values; with no environment set at all, it never runs | | `@envnot=prod` | skipped when the environment matches | | `@report=false` | **not** a selection tag — the scenario runs normally, but its step detail is kept out of the reports, which is how a login or token-fetch scenario avoids publishing a secret | `@setup` deserves a second look because its behaviour surprises people: it exists so that a feature can build its own data by calling a scenario that the runner will never pick up on its own. It behaves exactly like `@ignore` as far as selection is concerned. ## Getting an ignored scenario to run anyway There are three legitimate routes, and none of them is a tag expression: - **By line.** `Runner.path("classpath:api/orders.feature:31")` runs the scenario at line 31 whatever it is tagged. This is what an IDE's "run this scenario" gutter action uses, and it is why you can click into an `@ignore`d scenario and watch it execute. - **By name.** `scenarioName("creates an order")` matches on the exact scenario name and bypasses the tag layer the same way. - **By call.** `call read('helper.feature')` from another feature runs the callee's scenarios with tag filtering switched off, which is why helper features are usually tagged `@ignore` — to keep them out of the top-level run while remaining fully callable. ## Environment tags and a common misread `@env` and `@envnot` are checked against the value you gave `karateEnv(...)` — or the `karate.env` system property, which the runner reads for you. Two edges are worth memorising: - **`@env=qa` with no environment configured never runs.** A missing environment is not a wildcard; it fails the check. - **`@envnot=prod` with no environment configured does run.** The exclusion needs a value to compare against, so with nothing set there is nothing to exclude. That asymmetry means a suite that "works locally and skips half its scenarios in CI" is very often just a missing `-Dkarate.env`. ## One tag that is version-scoped Karate 2 recognises a `@lock` tag on the selection path's neighbours: `@lock=name` serialises scenarios sharing that name and `@lock=*` excludes everything else while it runs. Karate 1.x has no such tag and instead honours `@parallel=false` on a feature. The two are not interchangeable, and a 1.x feature carrying `@parallel=false` is simply ignored on 2.x — worth checking during a migration, because nothing fails, the scenarios just start overlapping.
- Why are Karate helper features so often tagged `@ignore`?Because the tag keeps them out of top-level selection while leaving them fully callable. A feature reached by `call read('helper.feature')` skips tag filtering entirely, so the helper never shows up as a scenario in its own right but still runs whenever another feature invokes it.
- An `@env=qa` scenario is skipped in a CI job that runs everything. What is the first thing to check?Whether an environment was set at all. `@env=qa` requires the runner's environment to equal one of its values, and an unset environment fails that check rather than matching everything. Set it with `karateEnv("qa")` on the builder or `-Dkarate.env=qa` on the command line.
- What does `@report=false` change about selection?Nothing. The scenario is selected and executed exactly as usual; only its step detail is suppressed in the generated reports. It exists so a scenario that fetches a token or posts credentials does not publish them into a shared HTML report, not to control which scenarios run.
saying these in an interview costs you the question
- Treating @ignore as an ordinary tag the selector evaluates
- Claiming tags("@ignore") will run the ignored scenarios
- Saying ~@ignore is required in every Karate runner
- Assuming an unset environment makes @env=qa match anything
- Thinking @report=false deselects the scenario
- Believing a called feature still obeys the runner's tag filter