{"record":{"id":"fc3fb869850e0bde","repo":"hashicorp/nomad","slug":"no-keyloader-object-to-perform-loadkeypair","errorCode":null,"errorMessage":"No Keyloader object to perform LoadKeyPair","messagePattern":"No Keyloader object to perform LoadKeyPair","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/tlsutil/config.go","lineNumber":204,"sourceCode":"\n\t// Read certificates and return an error if no valid certificates were\n\t// found. Unfortunately it is very difficult to return meaningful\n\t// errors as PEM files are extremely permissive.\n\tif !pool.AppendCertsFromPEM(data) {\n\t\treturn fmt.Errorf(\"Failed to parse any valid certificates in CA file: %s\", c.CAFile)\n\t}\n\n\treturn nil\n}\n\n// LoadKeyPair is used to open and parse a certificate and key file\nfunc (c *Config) LoadKeyPair() (*tls.Certificate, error) {\n\tif c.CertFile == \"\" || c.KeyFile == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tif c.KeyLoader == nil {\n\t\treturn nil, fmt.Errorf(\"No Keyloader object to perform LoadKeyPair\")\n\t}\n\n\tcert, err := c.KeyLoader.LoadKeyPair(c.CertFile, c.KeyFile)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Failed to load cert/key pair: %v\", err)\n\t}\n\treturn cert, err\n}\n\n// OutgoingTLSConfig generates a TLS configuration for outgoing\n// requests. It will return a nil config if this configuration should\n// not use TLS for outgoing connections. Provides a callback to\n// fetch certificates, allowing for reloading on the fly.\nfunc (c *Config) OutgoingTLSConfig() (*tls.Config, error) {\n\t// If VerifyServerHostname is true, that implies VerifyOutgoing\n\tif c.VerifyServerHostname {\n\t\tc.VerifyOutgoing = true\n\t}","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/tlsutil/config.go#L186-L222","documentation":"LoadKeyPair loads CertFile/KeyFile through the pluggable KeyLoader. If CertFile and KeyFile are both set but Config.KeyLoader is nil, there is no object to perform the load, so this error is returned. It is a configuration/initialization bug: TLS cert loading was requested but the loader dependency was never injected.","triggerScenarios":"Building a Config with both CertFile and KeyFile set and calling LoadKeyPair (directly or via OutgoingTLSConfig/IncomingTLSConfig) while KeyLoader remains nil — typically a hand-constructed Config instead of one initialized with the default loader.","commonSituations":"Constructing tlsutil.Config{} manually in code or tests and forgetting to set KeyLoader; upgrading library versions where the default loader is no longer auto-populated; copying config structs field-by-field and dropping the loader.","solutions":["Set Config.KeyLoader to the library's default key loader before calling LoadKeyPair.","If no cert/key pair is needed, clear CertFile/KeyFile (LoadKeyPair then returns nil, nil).","Check how the Config is built/decoded to ensure the KeyLoader field is populated (it is not a serialized field).","In tests, use the same initialization helper production code uses instead of a zero-value Config."],"exampleFix":"// before\ncfg := &tlsutil.Config{CertFile: cert, KeyFile: key}\ncert, err := cfg.LoadKeyPair() // No Keyloader object\n// after\ncfg := &tlsutil.Config{CertFile: cert, KeyFile: key, KeyLoader: &tlsutil.FileKeyLoader{}}\ncert, err := cfg.LoadKeyPair()","handlingStrategy":"validation","validationCode":"func (c *tlsutil.Config) validate() error {\n    if c.CertFile != \"\" && c.KeyFile != \"\" && c.KeyLoader == nil {\n        return errors.New(\"CertFile/KeyFile set but KeyLoader is nil; set a KeyLoader\")\n    }\n    return nil\n}\n// call cfg.validate() before LoadKeyPair / TLS config generation","typeGuard":"func hasUsableKeyLoader(c *tlsutil.Config) bool {\n    return c.CertFile == \"\" || c.KeyFile == \"\" || c.KeyLoader != nil\n}","tryCatchPattern":"cert, err := cfg.LoadKeyPair()\nif err != nil && err.Error() == \"No Keyloader object to perform LoadKeyPair\" {\n    return fmt.Errorf(\"tls config not initialized: %w\", err)\n}","preventionTips":["Always construct tlsutil.Config through the library's constructor/default initializer, not a zero-value struct literal.","Set KeyLoader explicitly in code-based configuration and test fixtures.","Add a config-validate step that rejects CertFile/KeyFile without a KeyLoader at startup.","When copying Config structs, copy/replace the loader field too."],"tags":["tls","configuration","nil-pointer","dependency-injection"],"backgroundTag":"missing-keyloader-config","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}