{"record":{"id":"6afd40d4477c2386","repo":"istio/istio","slug":"qat-configuration-is-required","errorCode":null,"errorMessage":"qat configuration is required","messagePattern":"qat configuration is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/validation/agent/validation.go","lineNumber":490,"sourceCode":"\t}\n\n\tswitch pkpConf.GetProvider().(type) {\n\tcase *meshconfig.PrivateKeyProvider_Cryptomb:\n\t\tcryptomb := pkpConf.GetCryptomb()\n\t\tif cryptomb == nil {\n\t\t\terrs = multierror.Append(errs, errors.New(\"cryptomb configuration is required\"))\n\t\t} else {\n\t\t\tpollDelay := cryptomb.GetPollDelay()\n\t\t\tif pollDelay == nil {\n\t\t\t\terrs = multierror.Append(errs, errors.New(\"pollDelay is required\"))\n\t\t\t} else if pollDelay.GetSeconds() == 0 && pollDelay.GetNanos() == 0 {\n\t\t\t\terrs = multierror.Append(errs, errors.New(\"pollDelay must be non zero\"))\n\t\t\t}\n\t\t}\n\tcase *meshconfig.PrivateKeyProvider_Qat:\n\t\tqatConf := pkpConf.GetQat()\n\t\tif qatConf == nil {\n\t\t\terrs = multierror.Append(errs, errors.New(\"qat configuration is required\"))\n\t\t} else {\n\t\t\tpollDelay := qatConf.GetPollDelay()\n\t\t\tif pollDelay == nil {\n\t\t\t\terrs = multierror.Append(errs, errors.New(\"pollDelay is required\"))\n\t\t\t} else if pollDelay.GetSeconds() == 0 && pollDelay.GetNanos() == 0 {\n\t\t\t\terrs = multierror.Append(errs, errors.New(\"pollDelay must be non zero\"))\n\t\t\t}\n\t\t}\n\tdefault:\n\t\terrs = multierror.Append(errs, errors.New(\"unknown private key provider\"))\n\t}\n\n\treturn errs\n}\n\n// ValidateConnectTimeout validates the envoy connection timeout\nfunc ValidateConnectTimeout(timeout *durationpb.Duration) error {\n\tif err := ValidateDuration(timeout); err != nil {","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/istio/istio/blob/8dc789c5cf17517c64e3c36cb3288230f149dfae/pkg/config/validation/agent/validation.go#L472-L508","documentation":"Thrown by validatePrivateKeyProvider when the provider oneof selects the qat case but GetQat() returns nil — the oneof type wrapper exists while the QAT (Intel QuickAssist) sub-message is missing. Mirrors the cryptomb check: a chosen provider must carry its configuration.","triggerScenarios":"`privateKeyProvider: {qat: null}` in JSON mesh config, or a programmatically built PrivateKeyProvider with the Qat case set but a nil Qat message, validated via ValidateMeshConfigProxyConfig.","commonSituations":"JSON patches setting qat to null; hand-written JSON configs declaring qat with no body; serialization tools that emit explicit nulls for empty messages.","solutions":["Provide the qat message with a pollDelay: `privateKeyProvider: {qat: {pollDelay: 5s}}`.","In JSON, omit the `qat` key rather than writing null.","Drop privateKeyProvider entirely if QAT hardware is not in use."],"exampleFix":"# before (JSON)\n\"privateKeyProvider\": {\"qat\": null}\n\n# after\n\"privateKeyProvider\": {\"qat\": {\"pollDelay\": \"5s\"}}","handlingStrategy":"validation","validationCode":"if _, ok := pkp.GetProvider().(*meshconfig.PrivateKeyProvider_Qat); ok && pkp.GetQat() == nil {\n    return fmt.Errorf(\"qat case set but message is null; provide pollDelay or drop the key\")\n}","typeGuard":"func isConcreteQat(pkp *meshconfig.PrivateKeyProvider) bool {\n\tq, ok := pkp.GetProvider().(*meshconfig.PrivateKeyProvider_Qat)\n\treturn ok && q != nil && q.Qat != nil\n}","tryCatchPattern":null,"preventionTips":["Avoid null-valued oneof entries in JSON configs.","Use YAML with a populated qat body: `qat: {pollDelay: 5s}`."],"tags":["istio","mesh-config","private-key-provider","qat","protobuf","validation","go"],"backgroundTag":null,"analyzedSha":"8dc789c5cf17517c64e3c36cb3288230f149dfae","analyzedAt":"2026-08-15T15:16:55.434Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}