owasp-amass/amass · error

failed to obtain the registered domain name FQDN for: %s

Error message

failed to obtain the registered domain name FQDN for: %s

What it means

getRegisteredDomainEntity looks up the registered-domain FQDN entity in the graph by filtering entities of type oam.FQDN on content name == dr.Domain. If exactly one match is not found (query error, zero matches, or multiple matches), the registered domain entity cannot be associated and this error is returned. It ensures scope relationships are only created against a canonical registered-domain entity.

Source

Thrown at engine/plugins/horizontals/plugin.go:493

	}
}

func (h *horizPlugin) getRegisteredDomainEntity(sess et.Session, record *dbt.Entity) (*dbt.Entity, error) {
	dr, valid := record.Asset.(*oamreg.DomainRecord)
	if !valid {
		return nil, errors.New("failed to cast the DomainRecord")
	}

	ctx, cancel := context.WithTimeout(sess.Ctx(), 30*time.Second)
	defer cancel()

	if ents, err := sess.DB().FindEntitiesByContent(ctx, oam.FQDN, time.Time{}, 1, dbt.ContentFilters{
		"name": dr.Domain,
	}); err == nil && len(ents) == 1 {
		return ents[0], nil
	}

	return nil, fmt.Errorf("failed to obtain the registered domain name FQDN for: %s", dr.Domain)
}

func (h *horizPlugin) getRegisteredNetblockEntity(sess et.Session, record *dbt.Entity) (*dbt.Entity, error) {
	iprec, valid := record.Asset.(*oamreg.IPNetRecord)
	if !valid {
		return nil, errors.New("failed to cast the IPNetRecord")
	}

	ctx, cancel := context.WithTimeout(sess.Ctx(), 30*time.Second)
	defer cancel()

	if ents, err := sess.DB().FindEntitiesByContent(ctx, oam.Netblock, time.Time{}, 1, dbt.ContentFilters{
		"cidr": iprec.CIDR.String(),
	}); err == nil && len(ents) == 1 {
		return ents[0], nil
	}

	return nil, fmt.Errorf("failed to obtain the registered CIDR Netblock for: %s", iprec.CIDR.String())

View on GitHub (pinned to 79299dce87)

Solutions

  1. Ensure the apex/registered domain is discovered and stored before processing its subdomains, or create the entity on demand here.
  2. Normalize name casing/format before the content filter to avoid duplicate/mismatched entities.
  3. Deduplicate FQDN entities in the graph so exactly one entity exists per registered domain.
  4. Check the DB error from FindEntitiesByContent — a storage failure surfaces here as len(ents)==0 via err == nil being false.
  5. Relax the len(ents) == 1 requirement to len(ents) >= 1 and take the first match if duplicates are tolerated.

Example fix

// before
if ents, err := sess.DB().FindEntitiesByContent(ctx, oam.FQDN, time.Time{}, 1, dbt.ContentFilters{"name": dr.Domain}); err == nil && len(ents) == 1 {
	return ents[0], nil
}
return nil, fmt.Errorf("failed to obtain the registered domain name FQDN for: %s", dr.Domain)
// after
ents, err := sess.DB().FindEntitiesByContent(ctx, oam.FQDN, time.Time{}, 1, dbt.ContentFilters{"name": dr.Domain})
if err != nil {
	return nil, fmt.Errorf("failed to obtain the registered domain name FQDN for: %s: %w", dr.Domain, err)
}
if len(ents) == 0 {
	return nil, fmt.Errorf("registered domain FQDN entity not found for: %s", dr.Domain)
}
return ents[0], nil
Defensive patterns

Strategy: fallback

Validate before calling

// ensure apex exists before processing subdomains
ents, _ := sess.DB().FindEntitiesByContent(ctx, oam.FQDN, time.Time{}, 1, dbt.ContentFilters{"name": dr.Domain})
if len(ents) == 0 {
	// create or discover the apex entity first
}

Try / catch

domEnt, err := getRegisteredDomainEntity(sess, dr)
if err != nil {
	// log and continue; scope link is optional
	return nil
}

Prevention

When it happens

Trigger: sess.DB().FindEntitiesByContent(ctx, oam.FQDN, time.Time{}, 1, {"name": dr.Domain}) errors, returns 0 entities (domain record never discovered/stored), or returns >1 entities (len(ents) != 1) for the domain discovered via processDomainRecord/processInScope.

Common situations: Processing a subdomain whose apex domain has not yet been added to the graph (ordering issue); the apex was discovered but stored with different casing; multiple FQDN entities share the name due to re-discovery; DB query failure.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06). Data as JSON: /api/errors/a9221528403b2697. Report an issue: GitHub.