kt policy lint: Catching Errors Before Deployment
The cheapest policy incident to fix is the one that never reaches the gateway. kt policy lint is the first gate in that process. It validates policy-config.yaml against the Keeptrusts schema, catches unknown policy kinds and invalid fields, checks for missing required structure, and does it locally before any traffic or rollout is involved.
Use this page when
- You want a fast pre-merge or pre-deploy validation step for policy configuration.
- You need a practical explanation of what linting catches and what it does not.
- You want a simple case for why every config change should pass
kt policy lintbefore anyone starts the gateway.
Primary audience
- Primary: Technical Engineers and platform maintainers
- Secondary: Technical Leaders, QA teams, release managers
The problem
Policy configuration errors are usually boring, and that is exactly why they are dangerous. A typo in a policy name, an invalid field inside a policy block, or a chain entry with no matching config can all slip through code review because the YAML looks roughly right to a human reader.
The problem gets worse when teams move quickly. Someone copies a known-good config, edits one field, and assumes the shape is still valid. Another person adds a policy to the chain but forgets to add its config block. A third person invents a field name based on intuition rather than the schema.
None of these failures are sophisticated, but every one of them can delay rollout or create runtime confusion. They also waste time because engineers often notice them too late, after the gateway is already part of a manual test or deployment flow.
That is why linting matters. It moves the failure to the earliest, cheapest point in the workflow.
The solution
kt policy lint --file policy-config.yaml validates the config structure before the runtime gets involved. It checks that the YAML parses, that required top-level structure is present, that policy kinds are recognized, that fields match schema expectations, that the chain is not empty, and that provider contradictions do not make the config internally inconsistent.
Just as important, it exposes clear error classes. The current docs call out examples such as:
E001for an unknown policy kindE002for an unknown fieldE003for a chain entry with no config block
Those are exactly the errors teams should want to catch before any human tries to reason about runtime behavior.
Implementation
The core command is deliberately simple:
kt policy lint --file policy-config.yaml
kt policy lint --file policy-config.yaml --json
A small broken config shows why the command is useful:
pack:
name: broken-demo
version: 0.2.0
enabled: true
policies:
chain:
- prompt-injections
- pii-detector
- quality-scorer
policy:
pii-detector:
actions: redact
This config contains three very ordinary problems.
prompt-injectionsis the wrong policy kind name.actionsis not the valid field forpii-detector.quality-scorerappears in the chain but has no config block.
That is exactly the class of mistake lint is meant to intercept. The command fails before the team wastes time starting a gateway or interpreting incomplete behavior.
There are two good ways to use the command.
The first is interactive authoring. Run lint immediately after you edit the config, fix the reported shape issues, and keep moving.
The second is CI gating. In that mode, --json is usually the better choice because machine-readable output makes failure handling obvious and consistent. The docs also note that lint exits with code 2 on validation failure, which makes it easy to wire into automated pipelines.
The critical nuance is that lint is not the whole safety net. It proves the config is structurally valid. It does not prove the behavior is what you want. That is the next job for kt policy test --json.
Still, linting deserves to be its own mandatory step. Behavior tests are much more informative when they run against a config that is already known to be well-formed.
Results and impact
Teams that use lint consistently usually see the benefit in review speed more than in runtime metrics.
Pull requests are easier to evaluate because obvious schema problems are already filtered out. Engineers stop spending review time on typo-level mistakes and start spending it on actual policy design. Startup loops get faster because the gateway is not being used as a schema validator. Release pipelines become more predictable because broken configs fail at the earliest step.
The broader impact is cultural. kt policy lint nudges the team toward treating policy as code with the same expectations they already bring to type-checking or schema validation elsewhere.
Key takeaways
kt policy lintis the first quality gate forpolicy-config.yaml.- It catches schema errors, unknown policy kinds, invalid fields, missing required structure, and logical contradictions.
--jsonis the best mode for CI because it gives structured results and a clear exit status.- Lint proves structure, not behavior. It should always be followed by
kt policy test --jsonfor meaningful rollout confidence. - Running lint before startup is the cheapest way to avoid avoidable config incidents.