In ktlint 1.x, how do you suppress a single rule violation for one declaration or file?
answer
- Not a comment directive any more
- A plain Kotlin annotation does it
- Rule ids carry a rule-set prefix
- File-level needs the @file: target
- @Suppress("ktlint:standard:...")
basics
~20 sAnnotate the code with Kotlin's @Suppress using the fully qualified rule id, for example @Suppress("ktlint:standard:function-naming") on the declaration, or @file:Suppress(...) at the top of the file. The old ktlint-disable comments were removed in ktlint 1.0.
solid answer
~40 sSince ktlint 1.0 the only inline suppression mechanism is Kotlin's own `@Suppress` annotation, carrying the **fully qualified rule id**: `@Suppress("ktlint:standard:function-naming")` for a rule from the standard rule set, or `@Suppress("ktlint:my-ruleset:my-rule")` for a custom one. Put it on the declaration you want covered — a class, function or property — and it applies to that element and everything nested inside it; use `@file:Suppress(...)` above the package declaration to cover the whole file. `@Suppress("ktlint")` silences every ktlint rule on that element, which is usually too blunt: prefer the specific id so a *different* violation still surfaces later. The `// ktlint-disable` / `// ktlint-enable` comment directives were deprecated in 0.50 and no longer do anything in 1.x. Inline suppression is for a deliberate local exception; a project-wide decision belongs in configuration instead.
code
kotlin · 8 lines@file:Suppress("ktlint:standard:filename")
package com.example.orders
class OrderMath {
@Suppress("ktlint:standard:function-naming")
fun Add_Legacy(a: Int, b: Int): Int = a + b
}go deeper
Be ready to write the annotation correctly from memory: @Suppress with the ktlint: prefix and the rule-set-qualified id, on the declaration, or @file:Suppress above the package line for a whole file.
Explain why the bare id silently fails — the Kotlin compiler ignores unknown suppression strings — and that the comment directives were removed in ktlint 1.0 rather than merely deprecated.
Show judgment about scope: the narrowest annotation that covers the real exception, with a reviewer-visible reason, instead of blanket suppression that hides violations nobody has evaluated.
Own the policy question: which rules a team is allowed to suppress inline at all, versus rules that must be argued centrally, and how you audit accumulated suppressions so they do not become permanent invisible debt.
## What this question is really about ktlint is a linter and formatter for Kotlin. Like every linter, it needs an escape hatch: a place where a rule is right in general but wrong for one specific piece of code — a JUnit test method whose name is deliberately written in backticks or upper camel case, a generated-looking constant, a Kotlin file that mirrors a foreign API's naming. The interviewer is checking that you know the *current* escape hatch, because ktlint changed it in a breaking way at version 1.0 and a lot of blog posts and Stack Overflow answers still show the old one. ## The current mechanism: @Suppress with a qualified rule id ktlint honours Kotlin's standard `@Suppress` annotation. The string you pass is the ktlint rule id, prefixed with `ktlint:` and qualified with the id of the rule set it comes from: - `@Suppress("ktlint:standard:function-naming")` — a rule from ktlint's built-in `standard` rule set. - `@Suppress("ktlint:my-ruleset:my-rule")` — a rule from a custom rule set you or a third party wrote. - `@Suppress("ktlint")` — every ktlint rule, on that element. The qualification matters. Rule ids became fully qualified with their rule set id in the 0.49 line, so a bare `@Suppress("function-naming")` is not a ktlint suppression at all — the Kotlin compiler simply ignores an unknown suppression string, so the annotation compiles fine and the ktlint violation still fails your build. That silent no-op is exactly the trap this question probes. ## Scope: where you put the annotation `@Suppress` is an ordinary Kotlin annotation, so it obeys ordinary Kotlin scoping rules rather than anything ktlint-specific: - On a **declaration** — a class, object, function, property — it covers that declaration and everything nested inside it. Annotating a class suppresses the rule for all of its members. - As a **file-level annotation**, written as `@file:Suppress("ktlint:standard:filename")` above the `package` line, it covers the entire file. This is the form you need for rules that are inherently file-scoped, such as filename or import rules, because there is no single declaration to hang them on. There is no way to suppress a rule for a *range of lines* any more; that was precisely what the removed comment directives did. ## What replaced the comment directives Older ktlint supported `// ktlint-disable` at the end of a line, and a `// ktlint-disable <rule-id>` / `// ktlint-enable <rule-id>` pair to bracket a block. Those were deprecated in the 0.50 release and removed in ktlint 1.0. In a 1.x codebase they are inert comments: they neither suppress anything nor warn you loudly at the point of use. If you inherit a codebase full of them, expect a wave of "new" violations the moment you upgrade — the code did not change, the suppressions simply stopped applying. The reason for the change is worth being able to state: `@Suppress` is part of the language, so it is visible to the compiler, to IntelliJ, and to anyone reading the code, and it is scoped by the same rules as everything else in Kotlin. A comment directive is invisible to all of that and has to be re-implemented by every tool. ## Choosing the right instrument Inline suppression is one of three ways to make a ktlint violation go away, and interviewers like candidates who reach for the narrowest one: - **Fix the code.** The default. Most ktlint findings are trivially correctable. - **`@Suppress` on the declaration.** For a genuine local exception, where the surrounding code should still be checked. The annotation sits next to the code, so a reviewer sees the exception and can challenge it. - **Configuration.** When the rule is simply not this project's policy, turning it off centrally is honest and keeps the code free of annotation noise; a baseline serves the separate purpose of grandfathering pre-existing violations during adoption. A weak answer suppresses broadly — `@Suppress("ktlint")` on a whole class, or a file-level suppression to silence one function — because it hides violations nobody has looked at yet. A strong answer picks the narrowest scope and the exact rule id, and can explain why the annotation is preferable to sprinkling a rule off across the project.
- What does @Suppress("ktlint") do, and when is it a bad idea?It suppresses every ktlint rule for the annotated element and everything inside it. That is fine for a single line you have thought about, but on a class or file it also hides violations that do not exist yet — a future formatting or naming mistake in that scope will never be reported. Name the specific rule id unless you truly mean "exempt all of this from linting".
- You upgrade a project from ktlint 0.4x to 1.x and suddenly get hundreds of violations in untouched files. What is the likely cause?The old `// ktlint-disable` comments stopped working — they were removed in 1.0, so every violation they were hiding is now reported. The comments are still in the source but inert. The fix is mechanical: convert each one to a `@Suppress` with the fully qualified rule id on the enclosing declaration, or decide the rule should be off project-wide.
A @Suppress with a specific rule id is a doctor's note excusing one student from one class; @Suppress("ktlint") on a whole file excuses the entire class from school, and nobody notices what else they miss.
saying these in an interview costs you the question
- Says // ktlint-disable comments still work in ktlint 1.x
- Writes @Suppress with a bare, unqualified rule id
- Reaches for @Suppress("ktlint") on a whole class by default
- Thinks suppression requires a baseline file entry
- Assumes a mid-file comment can suppress a range of lines