projectdiscovery/nuclei · error

%s is not a named struct type

Error message

%s is not a named struct type

What it means

The scraper looked up typeName in the package's scope, found it, but its Underlying() type is not *types.Struct. Scrape only supports named struct types: interfaces, maps, slices, basic types, signatures, and pointer/alias chains ending outside a struct are rejected here.

Source

Thrown at pkg/js/devtools/tsgen/scrape.go:39

	// get package
	pkg, ok := p.imports[pkgName]
	if !ok {
		return errkit.Newf("package %v for type %v not found", pkgName, typeName)
	}
	// get type
	obj := pkg.Types.Scope().Lookup(baseTypeName)
	if obj == nil {
		return errkit.Newf("type %v not found in package %+v", typeName, pkg)
	}
	// Ensure the object is a type name
	typeNameObj, ok := obj.(*types.TypeName)
	if !ok {
		return errkit.Newf("%v is not a type name", typeName)
	}
	// Ensure the type is a named struct type
	namedStruct, ok := typeNameObj.Type().Underlying().(*types.Struct)
	if !ok {
		return fmt.Errorf("%s is not a named struct type", typeName)
	}
	// fmt.Printf("got named struct %v\n", namedStruct)
	// Iterate over the struct fields
	d := &ExtObject{
		builtIn: make(map[string]string),
		nested:  map[string]map[string]*ExtObject{},
	}

	// fmt.Printf("fields %v\n", namedStruct.NumFields())
	for i := 0; i < namedStruct.NumFields(); i++ {
		field := namedStruct.Field(i)
		fieldName := field.Name()
		if field.Exported() {
			recursiveScrapeType(nil, fieldName, field.Type(), d)
		}
	}
	entityMap := make(map[string]Entity)
	// convert ExtObject to Entity

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Give the binding a concrete named struct instead: wrap the non-struct type in a struct (e.g. struct{ Items []Item })
  2. Keep non-struct helper types out of the scraped API surface (unexport them or move them out of the module dir)
  3. If the type genuinely must be exposed, extend the scraper to handle the kind — report an issue

Example fix

// before
type Permissions map[string]bool   // scraped -> error

// after
type Permissions struct { Allow map[string]bool }
Defensive patterns

Strategy: type-guard

Type guard

func isNamedStruct(pkg *types.Package, typeName string) bool {
    obj := pkg.Scope().Lookup(typeName)
    if obj == nil { return false }
    tn, ok := obj.(*types.TypeName)
    if !ok { return false }
    _, ok = tn.Type().Underlying().(*types.Struct)
    return ok
}

Try / catch

In scraper code, check the guard above before scraping and skip non-struct types with a warning; as a lib author, catch the message at codegen time and restructure the offending type into a struct.

Prevention

When it happens

Trigger: tsgen trying to scrape a type like type FS = fs.FS (alias), type Handler interface{...}, type List []Item, or type ID string — all reachable in scope but not structs.

Common situations: Binding APIs that expose idiomatic Go alias/interface types; generics instantiations; standard-library types aliased into a lib's surface.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/d501388ccfc7628c. Report an issue: GitHub.