coredns/coredns · error

RR in %q is not a DNSKEY: %d

Error message

RR in %q is not a DNSKEY: %d

What it means

When reading a DNSSEC key pair, readKeyPair parses the public key file into an RR and verifies it is a DNSKEY record. If dns.NewRR yields a record of any other type (checked via type assertion), the plugin rejects the pair, reporting the actual record type number found in the file.

Source

Thrown at plugin/sign/keys.go:82

	return pairs, nil
}

func readKeyPair(public, private string) (Pair, error) {
	rk, err := os.Open(filepath.Clean(public))
	if err != nil {
		return Pair{}, err
	}
	b, err := io.ReadAll(rk)
	if err != nil {
		return Pair{}, err
	}
	dnskey, err := dns.NewRR(string(b))
	if err != nil {
		return Pair{}, err
	}
	if _, ok := dnskey.(*dns.DNSKEY); !ok {
		return Pair{}, fmt.Errorf("RR in %q is not a DNSKEY: %d", public, dnskey.Header().Rrtype)
	}
	ksk := dnskey.(*dns.DNSKEY).Flags&(1<<8) == (1<<8) && dnskey.(*dns.DNSKEY).Flags&1 == 1
	if !ksk {
		return Pair{}, fmt.Errorf("DNSKEY in %q is not a CSK/KSK", public)
	}

	rp, err := os.Open(filepath.Clean(private))
	if err != nil {
		return Pair{}, err
	}
	privkey, err := dnskey.(*dns.DNSKEY).ReadPrivateKey(rp, private)
	if err != nil {
		return Pair{}, err
	}
	switch signer := privkey.(type) {
	case *ecdsa.PrivateKey:
		return Pair{Public: dnskey.(*dns.DNSKEY), KeyTag: dnskey.(*dns.DNSKEY).KeyTag(), Private: signer}, nil
	case ed25519.PrivateKey:

View on GitHub (pinned to 558c9757a9)

Solutions

  1. Regenerate or export the correct DNSKEY public key file (e.g. with dnssec-keygen / delv output)
  2. Confirm the .key file's first record line starts with the zone name and 'IN DNSKEY'
  3. Re-download the key ensuring you capture the DNSKEY RR, not the DS or other records from the query
  4. Point the keys directive at the K<zone>+alg+tag.key file produced by dnssec-keygen

Example fix

// before (key file holds a DS record)
example.org. 3600 IN DS 12345 13 2 abcdef...
// after (key file must hold DNSKEY)
example.org. 3600 IN DNSKEY 257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0nAKFkXe3a0uPcaU==
Defensive patterns

Strategy: validation

Validate before calling

// Verify the public key file contains a DNSKEY RR before use:
b, _ := os.ReadFile(publicKeyPath)
rr, err := dns.NewRR(string(b))
if err != nil || _, ok := rr.(*dns.DNSKEY); !ok {
    // not a DNSKEY; regenerate or re-export
}

Prevention

When it happens

Trigger: Passing a file that is not a DNSKEY RR — e.g. a DS record, a zone file fragment, an HTML error page from a failed key download, or a DNSKEY response including RRSIG — as the public key argument to the keys directive.

Common situations: Downloading a key from a DNS lookup and saving the wrong RR (DS instead of DNSKEY); using ldns-verify output or a .key file that actually holds a DS; key file mixed up with zone data.

Related errors


AI-assisted analysis of coredns/coredns@558c9757a9 (2026-09-06). Data as JSON: /api/errors/979818ea9adbc50b. Report an issue: GitHub.