{"record":{"id":"c42bd4469aebe2ce","repo":"owasp-amass/amass","slug":"failed-to-cast-the-ipnetrecord","errorCode":null,"errorMessage":"failed to cast the IPNetRecord","messagePattern":"failed to cast the IPNetRecord","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/plugins/horizontals/plugin.go","lineNumber":499,"sourceCode":"\t\treturn nil, errors.New(\"failed to cast the DomainRecord\")\n\t}\n\n\tctx, cancel := context.WithTimeout(sess.Ctx(), 30*time.Second)\n\tdefer cancel()\n\n\tif ents, err := sess.DB().FindEntitiesByContent(ctx, oam.FQDN, time.Time{}, 1, dbt.ContentFilters{\n\t\t\"name\": dr.Domain,\n\t}); err == nil && len(ents) == 1 {\n\t\treturn ents[0], nil\n\t}\n\n\treturn nil, fmt.Errorf(\"failed to obtain the registered domain name FQDN for: %s\", dr.Domain)\n}\n\nfunc (h *horizPlugin) getRegisteredNetblockEntity(sess et.Session, record *dbt.Entity) (*dbt.Entity, error) {\n\tiprec, valid := record.Asset.(*oamreg.IPNetRecord)\n\tif !valid {\n\t\treturn nil, errors.New(\"failed to cast the IPNetRecord\")\n\t}\n\n\tctx, cancel := context.WithTimeout(sess.Ctx(), 30*time.Second)\n\tdefer cancel()\n\n\tif ents, err := sess.DB().FindEntitiesByContent(ctx, oam.Netblock, time.Time{}, 1, dbt.ContentFilters{\n\t\t\"cidr\": iprec.CIDR.String(),\n\t}); err == nil && len(ents) == 1 {\n\t\treturn ents[0], nil\n\t}\n\n\treturn nil, fmt.Errorf(\"failed to obtain the registered CIDR Netblock for: %s\", iprec.CIDR.String())\n}\n","sourceCodeStart":481,"sourceCodeEnd":513,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/engine/plugins/horizontals/plugin.go#L481-L513","documentation":"getRegisteredNetblockEntity expects record.Asset to be an *oamreg.IPNetRecord so it can resolve the registered netblock entity. The type assertion failure means the entity handed to it carries a different asset type. It is a guard against routing non-netblock entities into the netblock registration lookup.","triggerScenarios":"processInScope or processIPNetRecord passes an entity whose Asset is not *oamreg.IPNetRecord (e.g. an IPAddress or Netblock asset instead of the registration record) into getRegisteredNetblockEntity.","commonSituations":"Event-graph relations forwarding raw netblock/IP assets instead of registration records; new plugins emitting netblock data without wrapping it in oamreg.IPNetRecord; asset type changes after a library upgrade.","solutions":["Type-check record.Asset.(*oamreg.IPNetRecord) before calling and silently skip mismatches","Ensure processIPNetRecord is only fed events whose asset is *oamreg.IPNetRecord","Verify DB entity deserialization produces *oamreg.IPNetRecord for netblock registration content"],"exampleFix":"// before\nnb, err := h.getRegisteredNetblockEntity(sess, record)\nif err != nil {\n\treturn err\n}\n\n// after\nif _, ok := record.Asset.(*oamreg.IPNetRecord); !ok {\n\treturn nil\n}\nnb, err := h.getRegisteredNetblockEntity(sess, record)","handlingStrategy":"type-guard","validationCode":"if _, ok := record.Asset.(*oamreg.IPNetRecord); !ok {\n\treturn nil // not an IPNetRecord; skip\n}","typeGuard":"func isIPNetRecord(a interface{}) (*oamreg.IPNetRecord, bool) {\n\tr, ok := a.(*oamreg.IPNetRecord)\n\treturn r, ok\n}","tryCatchPattern":"if err != nil {\n\tif strings.Contains(err.Error(), \"failed to cast the IPNetRecord\") {\n\t\treturn nil // ignore non-netblock entities\n\t}\n\treturn err\n}","preventionTips":["Guard asset type before netblock registration lookups","Route events by asset type before calling helpers","Assert exact pointer types, not interfaces, when calling cast-dependent APIs"],"tags":["go","type-assertion","netblock"],"backgroundTag":"type-mismatch","analyzedSha":"79299dce87b0085db0f2f4ef3e9c52cccb49f514","analyzedAt":"2026-09-06T08:22:48.198Z","contentChangedAt":"2026-09-06T08:22:48.198Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}